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.HybsDateUtil; // 6.9.2.1 (2018/03/12) 030import org.opengion.fukurou.system.OgRuntimeException ; // 6.4.2.0 (2016/01/29) 031import org.opengion.fukurou.system.LogWriter; 032import org.opengion.fukurou.xml.DomParser; 033import org.w3c.dom.Document; 034import org.w3c.dom.Element; 035import org.w3c.dom.Node; 036import org.w3c.dom.NodeList; 037import org.w3c.dom.NamedNodeMap; // 6.9.2.0 (2018/03/05) 038 039import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE; // 6.1.0.0 (2014/12/26) refactoring 040 041/** 042 * DB設定XMLの内容をJAXBを利用してロードする 043 * Driverをロードする 044 * 上記2つの機能を備えたクラスです 045 * 046 * 外部からはgetDbidメソッドを利用してDB設定(ExpandedDbid型)を取得します。 047 * DB設定情報が無い場合にXMLを読みにいきます。 048 * このDBIDを決めるキーは、内部取り込み字に、大文字変換されますので、大文字・ 049 * 小文字の区別はありません。 050 * 051 * @og.rev 4.0.0.0 (2007/10/25) 新規作成 052 * @og.rev 5.1.7.0 (2010/06/01) org.opengion.fukurou.xml.jaxb.dbid 関係 廃止 053 * @og.group 初期化 054 * 055 * @version 4.0 056 * @author 高橋正和 057 * @since JDK6.0, 058 */ 059public class DatabaseConfig { 060 061 // fukurou内で完結させるため、HybsDataからは読み込まずにここに書く 062 private static final String DEFAULT_DRIVER = "oracle.jdbc.OracleDriver"; 063 064 // 6.4.3.3 (2016/03/04) 初期 DBConfig.xml ファイルの設定。 065 public static final String DB_CONFIG_FILE = "../DBConfig.xml" ; 066 067 // XMLファイル関連 068 private final String xmlFilename; // 5.7.2.2 (2014/01/24) 069 070 /** 6.4.3.1 (2016/02/12) Collections.synchronizedMap で同期処理を行います。 */ 071 private final Map<String, EDbid> dbidMap = Collections.synchronizedMap( new LinkedHashMap<>() ); // 5.6.7.0 (2013/07/27) 072 /** 6.4.3.1 (2016/02/12) Collections.synchronizedList で同期処理を行います。 */ 073 private final List<String> driverList = Collections.synchronizedList( new ArrayList<>() ); 074 075 // 5.6.7.0 (2013/07/27) プルダウンメニュー用の情報の、キャッシュ用変数。 076 private String codeKeyVal ; // 初めて要求されたときに、セットします。 077 078 // 5.6.6.0 (2013/07/05) 表題(title)属性を追加 079 private static final String[] DBID_INFO_KEYS 080 = { "dbidKey", "title", "url", "user", "password", "readonly" 081 , "mincount", "maxcount", "pooltime", "applicationInfo","property" }; 082 083 /* DBDRIVERのキーのを管理します。5.1.9.0 (2010/08/01) */ 084 private static final String DBDRIVER_CLASS_KEY = "class"; 085 086 /** 087 * 初期値を使ってXMLを読み込む 088 * xmlFilenameの初期値は../DBConfig.xml 089 * 090 * @og.rev 4.3.1.1 (2008/08/23) 自分のコンストラクターを呼ぶように修正 091 */ 092 public DatabaseConfig() { 093 this( DB_CONFIG_FILE ); 094 } 095 096 /** 097 * XMLファイルの名前を指定して読み込む 098 * 099 * @og.rev 5.1.9.0 (2010/08/01) クラスローダー外からでもDBConfig.xmlを取得できるようにする 100 * @og.rev 5.6.7.0 (2013/07/27) オブジェクト作成時に初期化も行っておきます。 101 * @og.rev 5.6.8.2 (2013/09/20) Tomcat8で、クラスローダーが変更されているのでその対応 102 * @og.rev 5.7.2.2 (2014/01/24) WEB-INF/classes フォルダがないと、xmlURL がnull になる対応。 103 * @og.rev 5.7.2.3 (2014/01/31) ファイルの存在チェックを追加します。 104 * @og.rev 6.4.3.3 (2016/03/04) 初期 DBConfig.xml ファイルの設定。 105 * @og.rev 6.6.0.0 (2016/12/01) コンテキストパスから、##バージョン番号を取り去った値を返すようにします。 106 * @og.rev 6.8.5.1 (2018/01/15) ClassLoader変数名を、clsl から、loader に変更(他の変数名と整合性を持たす)。 107 * 108 * @param infile XMLファイルの名前 109 */ 110 public DatabaseConfig( final String infile ) { 111 final String xmlfile = infile == null || infile.isEmpty() ? DB_CONFIG_FILE : infile ; // 引数が無い場合の初期設定を行います。 112 String fileName = null; 113 114 // 6.3.9.1 (2015/11/27) In J2EE, getClassLoader() might not work as expected. Use Thread.currentThread().getContextClassLoader() instead.(PMD) 115 final ClassLoader loader = Thread.currentThread().getContextClassLoader(); 116 URL xmlURL = loader.getResource( xmlfile ); 117 118 // 5.6.8.2 (2013/09/20) Tomcat8で、xmlURL が取得できなくなっている・・・ようだ。 119 // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..; 120 if( xmlURL == null ) { 121 xmlURL = loader.getResource( "/" ); // クラスパスのベースURL 122 // 5.7.2.2 (2014/01/24) Tomcat7で、WEB-INF/classes フォルダがないと、xmlURL がnull になる。 123 if( xmlURL != null ) { 124 final File temp = new File( xmlURL.getPath() , xmlfile ); 125 if( temp.exists() ) { fileName = temp.getAbsolutePath(); } 126 } 127 } 128 else { 129 fileName = xmlURL.getFile().replaceAll( "%23%23","##" ); // 6.6.0.0 (2016/12/01) 130 // 5.7.2.3 (2014/01/31) ファイルの存在チェックを追加します。 131 if( ! new File( fileName ).exists() ) { fileName = null; } 132 } 133 134 // 5.1.9.0 (2010/08/01) クラスローダー外からでもDBConfig.xmlを取得できるようにする 135 if( fileName == null && new File( xmlfile ).exists() ) { 136 fileName = xmlfile; 137 } 138 139 if( fileName == null ) { 140 // 5.5.7.2 (2012/10/09) コメント追加 141 final String errMsg = "DBConfig.xmlが見つかりません。File=[" + xmlfile + "]\n" 142 + " WEB-INF/classes フォルダがないと、相対パスで見つけることができません。" ; 143 throw new OgRuntimeException( errMsg ); 144 } 145 146 xmlFilename = fileName; 147 148 init(); // 5.6.7.0 (2013/07/27) 149 } 150 151 /** 152 * dbidKeyをキーにしてExpandedDbid型でマップの内容を返す。 153 * 存在しない場合はNULLを返します。 154 * キーが無い場合に初期化を行う。 155 * 156 * @og.rev 4.0.0.1 (2007/12/04) EDbid#clone() 廃止 157 * @og.rev 5.6.7.0 (2013/07/27) synchronized メソッドにします。 158 * @og.rev 6.0.0.1 (2014/04/25) Collections.synchronizedMap を使用します。 159 * 160 * @param key XMLで登録したdbidKey 161 * 162 * @return EDbid型オブジェクト 163 */ 164 public EDbid getDbid( final String key ) { 165 return dbidMap.get( key.toUpperCase( Locale.JAPAN ) ) ; 166 } 167 168 /** 169 * マップをクリアします。 170 * XMLファイルを再読み込みする場合に使用します。 171 * 172 * @og.rev 5.1.9.0 (2010/08/01) ドライバーのリストもクリアする。 173 * @og.rev 5.6.7.0 (2013/07/27) synchronized メソッドにします。 174 * @og.rev 6.0.0.1 (2014/04/25) Collections.synchronizedMap を使用します。 175 */ 176 public void reload() { 177 dbidMap.clear(); 178 driverList.clear(); 179 init(); 180 } 181 182 /** 183 * 初期化処理 184 * 185 * DB設定XMLファイル(DBConfig.xml)を読み込みます。 186 * このファイルから、ドライバーリストの取得、DBIDのオブジェクトマップの作成を 187 * 行います。 188 * EDbidオブジェクト は、環境変数で、共通の初期値を定義しておくことが可能です。 189 * 項目として、REALM_URL、REALM_NAME、REALM_PASSWORD が設定可能です。 190 * 191 * ドライバーリストの取得後、Class.forName で、ドライバの登録も行います。 192 * 193 * @og.rev 5.1.7.0 (2010/06/01) org.opengion.fukurou.xml.jaxb.dbid 関係 廃止 194 * @og.rev 5.6.7.0 (2013/07/27) dbidMap,driverList を書き込むのではなく、作成します。 195 */ 196 private void init() { 197 final Document doc = DomParser.read( new File(xmlFilename) ) ; 198 final Element firstRoot = doc.getDocumentElement(); 199 200 makeDriverList( firstRoot ); // 5.6.7.0 (2013/07/27) 201 202 // 5.6.7.0 (2013/07/27) を、かけておきます。 203 synchronized ( this ) { 204 for( final String dr : driverList ) { 205 try { 206 Class.forName( dr ); 207 } catch( final ClassNotFoundException ex ) { 208 final String errMsg = "ドライバクラスが見つかりません。[" + dr + "]" ; 209 LogWriter.log( errMsg ); 210 LogWriter.log( ex ); 211 } 212 } 213 } 214 215 final EDbid defDdbid = new EDbid(); // 初期値 216 defDdbid.setUrl( System.getenv( "REALM_URL" ) ); 217 defDdbid.setUser( System.getenv( "REALM_NAME" ) ); 218 defDdbid.setPassword( System.getenv( "REALM_PASSWORD" ) ); 219 220 makeDbidMap( firstRoot,defDdbid ); // 5.6.7.0 (2013/07/27) 221 } 222 223 /** 224 * ドライバーリストを取得します。 225 * 226 * DB設定XMLファイル(DBConfig.xml)の、class タグを取り込みます。 227 * このファイルから、ドライバーリストを取得します。 228 * 229 * 内部的に3段階の処理が実行されます。 230 * 第1Step:DBConfig.xml から、ドライバーリストを取得 231 * 第2Step:ドライバーリストが存在しない場合、環境変数の REALM_DRIVER からドライバーを取得 232 * 第3Step:それでも存在しない場合、このクラスの DEFAULT_DRIVER 定数 からドライバーを取得 233 * 234 * @og.rev 5.1.7.0 (2010/06/01) org.opengion.fukurou.xml.jaxb.dbid 関係 廃止 235 * @og.rev 5.1.9.0 (2010/08/01) ドライバ一覧のListをオブジェクト変数化 236 * @og.rev 5.6.7.0 (2013/07/27) driverList を書き込むのではなく、作成します。 237 * @og.rev 5.6.7.0 (2013/07/27) synchronized メソッドにします。 238 * 239 * @param element DB設定XMLファイルのElementオブジェクト 240 */ 241 private void makeDriverList( final Element element ) { 242 243 final NodeList list = element.getElementsByTagName( "class" ) ; 244 final int num = list.getLength(); 245 for( int i=0; i<num; i++ ) { 246 final Element cls = (Element)list.item(i); 247 driverList.add( cls.getTextContent() ); 248 } 249 250 if( driverList.isEmpty() ) { 251 final String realmDriver = System.getenv( "REALM_DRIVER" ); 252 if( realmDriver != null && realmDriver.length() > 0 ) { 253 driverList.add( realmDriver ); 254 } 255 } 256 257 if( driverList.isEmpty() ) { driverList.add( DEFAULT_DRIVER ); } 258 } 259 260 /** 261 * EDbidオブジェクトのマップを取得します。 262 * 263 * DB設定XMLファイル(DBConfig.xml)の、dbid タグを取り込みます。 264 * このファイルから、EDbidオブジェクトの属性情報を取得し、オブジェクトを構築します。 265 * 266 * EDbidオブジェクト は、初期値をコピーして、作成していきます。 267 * EDbidオブジェクトをマップから取り出すキーとなる、dbidKey は、大文字化して設定します。 268 * 269 * @og.rev 5.1.7.0 (2010/06/01) org.opengion.fukurou.xml.jaxb.dbid 関係 廃止 270 * @og.rev 5.1.9.0 (2010/08/01) Mapを返すように変更 271 * @og.rev 5.5.2.0 (2012/05/01) property追加 272 * @og.rev 5.6.6.0 (2013/07/05) 表題(title)属性の取得 273 * @og.rev 5.6.7.0 (2013/07/27) 内部MapをDBConfig.xmlの読み込み順に変更。 274 * @og.rev 5.6.7.0 (2013/07/27) dbidMap を書き込むのではなく、作成します。 275 * @og.rev 5.6.7.0 (2013/07/27) synchronized メソッドにします。 276 * @og.rev 5.6.7.1 (2013/08/09) DEFAULT と、RESOURCE の DBIDキーがなければ、内部的に作成します。 277 * @og.rev 5.6.8.0 (2013/09/06) RESOURCE の DBIDキーを内部作成時に、title も設定します。 278 * @og.rev 6.4.3.4 (2016/03/11) computeIfAbsent と、新しい clone(String) メソッドを使用する。 279 * @og.rev 6.8.2.4 (2017/11/20) 環境変数( ${env.XXXX} ) を処理できるようにします。 280 * @og.rev 6.9.2.0 (2018/03/05) dbidに、begin,end,step,var,items 属性を追加します。 281 * 282 * @param element DB設定XMLファイルのElementオブジェクト 283 * @param defDdbid 初期情報の設定された、EDbidオブジェクト 284 */ 285 private void makeDbidMap( final Element element , final EDbid defDdbid ) { 286 final NodeList list = element.getElementsByTagName( "dbid" ) ; 287 final int num = list.getLength(); 288 for( int i=0; i<num; i++ ) { 289 final Element ele = (Element)list.item(i); 290 final ForEachObject forEach = new ForEachObject( ele ); 291 292 while( forEach.hasNext() ) { 293 final NodeList childs = ele.getChildNodes(); 294 final int numChild = childs.getLength(); 295 final EDbid dbid = defDdbid.clone(); // 初期値をコピーして、作成 296 for( int j=0; j<numChild; j++ ) { 297 final Node nd = childs.item(j); 298 if( nd.getNodeType() == Node.ELEMENT_NODE ) { 299 final Element el = (Element)nd; 300 final String tag = el.getTagName(); 301// // 6.8.2.4 (2017/11/20) 環境変数( ${env.XXXX} ) を処理できるようにします。 302// final String txt = envText( el.getTextContent() ); 303 // 6.9.2.0 (2018/03/05) 変数の置き換え( ${var} )と、環境変数( ${env.XXXX} ) を処理します。 304 final String txt = forEach.getText( el.getTextContent() ); 305 306 // dbidKey は、toUpperCase して、大文字のみとする。 307 // 6.8.2.4 (2017/11/20) 環境変数( ${env.XXXX} ) を処理できるようにします。 308 if( "dbidKey".equals( tag ) ) { 309 if( txt != null && txt.length() > 0 ) { 310 dbid.setDbidKey( txt.toUpperCase( Locale.JAPAN ) ); 311 } 312 } 313 else if( "title".equals( tag ) ) { dbid.setTitle( txt ); } // 5.6.6.0 (2013/07/05) 表題(title)属性の取得 314 else if( "url".equals( tag ) ) { dbid.setUrl( txt ); } 315 else if( "user".equals( tag ) ) { dbid.setUser( txt ); } 316 else if( "password".equals( tag ) ) { dbid.setPassword( txt ); } 317 else if( "readonly".equals( tag ) ) { dbid.setReadonly( txt ); } 318 else if( "mincount".equals( tag ) ) { dbid.setMincount( txt ); } 319 else if( "maxcount".equals( tag ) ) { dbid.setMaxcount( txt ); } 320 else if( "pooltime".equals( tag ) ) { dbid.setPooltime( txt ); } 321 else if( "applicationInfo".equals( tag ) ) { dbid.setApplicationInfo( txt ); } 322 else if( "property".equals( tag ) ) { dbid.addProp( txt ); } // 5.5.2.0 (2012/05/01) 323 else { 324 System.err.println( "警告:dbid に新しい属性が、追加されています。" ); 325 } 326 } 327 } 328 dbidMap.put( dbid.getDbidKey(), dbid ); // 5.6.7.0 (2013/07/27) 復活 329 } 330 } 331 332 // 5.6.7.1 (2013/08/09) DEFAULT と、RESOURCE の DBIDキーがなければ、内部的に作成します。 333 // 6.4.3.4 (2016/03/11) computeIfAbsent と、新しい clone(String) メソッドを使用する。 334 // Map#computeIfAbsent : 戻り値は、既存の、または計算された値。追加有り、置換なし、削除なし 335 dbidMap.computeIfAbsent( "DEFAULT", k -> defDdbid.clone( "DEFAULT" ) ); // DEFAULT が存在するか確認する。 336 337 // 6.4.3.4 (2016/03/11) computeIfAbsent と、新しい clone(String) メソッドを使用する。 338 // Map#computeIfAbsent : 戻り値は、既存の、または計算された値。追加有り、置換なし、削除なし 339 dbidMap.computeIfAbsent( "RESOURCE", k -> defDdbid.clone( "RESOURCE" ) ); // RESOURCE が存在するか確認する。 340 } 341 342// /** 343// * 環境変数( ${env.XXX} )を含むテキストを処理します。 344// * 345// * 環境変数を含まない場合は、引数の orgTxt を返します。 346// * 347// * @og.rev 6.8.2.4 (2017/11/20) 環境変数( ${env.XXXX} ) を処理できるようにします。 348// * 349// * @param orgTxt 環境変数( ${env.XXX} )を含む可能性のあるテキスト 350// * @return 環境変数を処理したテキスト 351// */ 352// private String envText( final String orgTxt ) { 353// final int st = orgTxt.indexOf( "${env." ); 354// if( st >= 0 ) { 355// final int ed = orgTxt.indexOf( '}' , st ); 356// if( ed >= 0 ) { 357// final String envKey = orgTxt.substring( st + "${env.".length() , ed ); 358// final String envTxt = orgTxt.substring( 0,st ) + System.getenv( envKey ) + orgTxt.substring( ed+1 ); 359// return envText( envTxt ); // ループすべきだが、再帰処理で対応します。 360// } 361// else { 362// final String errMsg = xmlFilename + " の環境変数( ${env.XXX} )の整合性が取れていません。" + orgTxt ; 363// throw new OgRuntimeException( errMsg ); 364// } 365// } 366// 367// return orgTxt; 368// } 369 370 /** 371 * dbidの属性処理が、煩雑になってきたので、内部クラスにまとめます。 372 * 373 * begin,end,step,var,items 属性で、ループ処理を行うための設定を取得します。 374 * items が未指定の場合は、begin,end,step による、数字(文字列)の配列を返します。 375 * itemsが、定義されている場合は、カンマで分割後、文字列の配列を返します。 376 * それぞれ、初期値があり、begin=0 , end=0 or items要素数,step=1, 377 * 378 * @og.rev 6.9.2.1 (2018/03/12) dbidに、begin,end,step,var,items 属性を追加します。 379 */ 380 private static final class ForEachObject { 381 private final String attVar ; // var 属性の値を、${xxxx} に置き換えた文字列。未定義は、null 382 private final String[] items ; // items 属性のCSV分割か、begin,end,step の数字文字列の配列 383 384 private int idx = -1; // hasNext() で、先にアップするので、一つ引いておきます。 385 386 /** 387 * Elementオブジェクトを指定して、インスタンスを生成するコンストラクタです。 388 * 389 * @og.rev 6.9.2.1 (2018/03/12) dbidに、begin,end,step,var,items 属性を追加します。 390 * 391 * @param element DB設定XMLファイルのElementオブジェクト 392 */ 393 public ForEachObject( final Element ele ) { 394 // 6.9.2.0 (2018/03/05) dbidに、begin,end,step,var 属性を追加します。 395 if( ele.hasAttributes() ) { 396 final NamedNodeMap attNode = ele.getAttributes(); 397 final int attBgn = StringUtil.nval( getAttri( attNode,"begin" ),0 ); 398 final int attStp = StringUtil.nval( getAttri( attNode,"step" ),1 ); 399 final String tmpVar = getAttri( attNode,"var" ); 400 attVar = StringUtil.isNull( tmpVar ) ? null : "${" + tmpVar + "}" ; // 置換元定数を作成します。 401 402 final String endStr = getAttri( attNode,"end" ); 403 final String itms = getAttri( attNode,"items" ); 404 if( StringUtil.isNull( itms ) ) { 405 final int attEnd = StringUtil.nval( endStr,attBgn+1 ); // とりあえず 1回は回すため。 406 final List<String> list = new ArrayList<>(); 407 for( int i=attBgn; i<attEnd; i+=attStp ) { 408 list.add( String.valueOf( i ) ); 409 } 410 411 items = list.toArray( new String[list.size()] ) ; 412 } 413 else { 414 items = itms.split( "," ); 415 } 416 } 417 else { 418 attVar = null; 419 items = new String[] { "0" }; // 最低1回は回せるように。 420 } 421 } 422 423 /** 424 * 反復処理でさらに要素がある場合にtrueを返します。 425 * 426 * この判定で、内部カウンタを、プラスしていますので、 427 * ループ判定時にのみ、呼び出してください。 428 * 429 * @og.rev 6.9.2.1 (2018/03/12) 新規追加 430 * 431 * @return 反復処理でさらに要素がある場合はtrue 432 */ 433 public boolean hasNext() { return ++idx < items.length; } 434 435 /** 436 * 引数の文字列に対して、var 属性と item要素の置換を行います。 437 * 438 * さらに、${env.XXXX} 環境変数の置換と、日付文字列{@DATE.XXXX}の置換も 439 * 行います。 440 * この処理では、内部カウンタはアップしませんので、inTxt を替えて、何度でも 441 * 呼び出すことが可能です。 442 * 443 * @og.rev 6.9.2.1 (2018/03/12) 新規追加 444 * 445 * @param inTxt 置換元の文字列 446 * @return items属性に対応して置換された、文字列 447 */ 448 public String getText( final String inTxt ) { 449 String rtnTxt = StringUtil.replace( inTxt , attVar , items[idx] ); // attVar が null の場合、inTxt が戻される。 450 rtnTxt = StringUtil.replaceText( rtnTxt , "${env." , "}" , System::getenv ); // 環境変数置換 451 rtnTxt = StringUtil.replaceText( rtnTxt , "{@DATE." , "}" , HybsDateUtil::getDateFormat ); // 日付文字列置換 452 453 return rtnTxt; 454 } 455 456 /** 457 * 属性を取得する簡易メソッドです。 458 * 459 * 引数に、ノードのコレクションと、属性のキーワードを指定することで、属性値を返します。 460 * 461 * @og.rev 6.9.2.0 (2018/03/05) 新規追加 462 * 463 * @param nodeMap 名前を指定してアクセスできるノードのコレクション 464 * @param key 属性のキーワード 465 * @return 属性値(キーに対応する属性が無い場合は、null) 466 */ 467 private String getAttri( final NamedNodeMap nodeMap,final String key ) { 468 final Node attNode = nodeMap.getNamedItem( key ); 469 470// return attNode == null ? null : attNode.getNodeValue() ; 471 472 String rtnTxt = attNode == null ? null : attNode.getNodeValue() ; 473 474 rtnTxt = StringUtil.replaceText( rtnTxt , "${env." , "}" , System::getenv ); // 環境変数置換 475 rtnTxt = StringUtil.replaceText( rtnTxt , "{@DATE." , "}" , HybsDateUtil::getDateFormat ); // 日付文字列置換 476 477 return rtnTxt; 478 } 479 } 480 481 /* ------------------------------------------------------------------------------------ 482 * 483 * 以下は、DBConfig.xml編集用のメソッドです。 484 * 編集用のメソッドでは、オブジェクト化されたDBID及びDBDRIVERの情報は使用せずに、 485 * DBConfig.xmlからその情報を再度読み出して、SET/GETしています。 486 * (オブジェクトとして依存しているのは、DBConfig.xmlのファイル名のみです) 487 * 488 * ------------------------------------------------------------------------------------- 489 */ 490 /** 491 * DBIDとして管理している項目のキーの一覧を配列形式で返します。 492 * 493 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 494 * 495 * @return 項目のキー一覧 496 * @og.rtnNotNull 497 */ 498 public static String[] getDbidInfoKeys() { 499 return DBID_INFO_KEYS.clone(); 500 } 501 502 /** 503 * 全てのDBIDの属性情報のリスト(配列)で返します。 504 * 505 * 値の順番については、{@link #getDbidInfoKeys()}で返されるキーの一覧と同じです。 506 * 507 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 508 * @og.rev 5.5.2.1 (2012/05/07) propertiesを出力 509 * @og.rev 5.6.6.0 (2013/07/05) 表題(title)属性を追加 510 * @og.rev 5.6.7.0 (2013/07/27) 内部MapをDBConfig.xmlの読み込み順に変更。 511 * @og.rev 6.3.9.0 (2015/11/06) Use block level rather than method level synchronization.(PMD) 512 * 513 * @return 全てのDBIDの属性情報のリスト(配列) 514 * @og.rtnNotNull 515 * @see #getDbidInfoKeys() 516 */ 517 public String[][] getDbidInfo() { 518 // 6.3.9.0 (2015/11/06) 色々やりたいが、今はsynchronizedブロックにするだけにします。 519 synchronized( dbidMap ) { 520 String[][] dbidInfo = new String[dbidMap.size()][DBID_INFO_KEYS.length]; 521 int idx = 0; 522 for( final EDbid dbid : dbidMap.values() ) { 523 dbidInfo[idx][0] = dbid.getDbidKey(); 524 dbidInfo[idx][1] = dbid.getTitle(); // 5.6.6.0 (2013/07/05) 表題(title)属性を追加 525 dbidInfo[idx][2] = dbid.getUrl(); 526 dbidInfo[idx][3] = dbid.getUser(); 527 dbidInfo[idx][4] = dbid.getPassword(); 528 dbidInfo[idx][5] = String.valueOf( dbid.isReadonly() ); 529 dbidInfo[idx][6] = String.valueOf( dbid.getMincount() ); 530 dbidInfo[idx][7] = String.valueOf( dbid.getMaxcount() ); 531 dbidInfo[idx][8] = String.valueOf( dbid.getPooltime() ); 532 dbidInfo[idx][9] = String.valueOf( dbid.isApplicationInfo() ); 533 dbidInfo[idx][10]= String.valueOf( dbid.getProps().toString() ); // 5.5.2.1 (2012/05/07) 534 idx++; 535 } 536 537 return dbidInfo; 538 } 539 } 540 541 /** 542 * 全てのDBIDの属性情報のリスト(配列)をセットします。 543 * 544 * このメソッドを呼び出すと、DBConfig.xmlで定義されているDBID情報一覧を"一旦削除し"、 545 * その上で、引数のDBID情報一覧をDBConfig.xmlに書き込みます。 546 * 547 * 値の順番については、{@link #getDbidInfoKeys()}で返されるキーの一覧と同じです。 548 * 549 * 書き込みの直前に、同じフォルダにタイムスタンプを付加したバックアップファイルを作成します。 550 * 551 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 552 * @og.rev 5.6.7.0 (2013/07/27) 内部MapをDBConfig.xmlの読み込み順に変更。 553 * 554 * @param dbidVals 全てのDBIDの属性情報の配列の配列 555 * @see #getDbidInfoKeys() 556 */ 557 public void setDbidInfo( final String[][] dbidVals ) { 558 FileUtil.copy( xmlFilename, xmlFilename + "_" + System.currentTimeMillis() ); 559 560 final Document doc = DomParser.read( new File(xmlFilename) ) ; 561 final Element firstRoot = doc.getDocumentElement(); 562 deleteChildElements( firstRoot, "dbid" ); 563 564 if( dbidVals != null && dbidVals.length > 0 ) { 565 // 5.6.7.0 (2013/07/27) 内部MapをDBConfig.xmlの読み込み順に変更(なので、廃止)。 566 for( int i=0; i<dbidVals.length; i++ ) { 567 final Element newEle = doc.createElement( "dbid" ); 568 for( int j=0; j<dbidVals[i].length; j++ ) { 569 final Element newChEle = doc.createElement( DBID_INFO_KEYS[j] ); 570 newChEle.setTextContent( dbidVals[i][j] ); 571 newEle.appendChild( newChEle ); 572 } 573 firstRoot.appendChild( newEle ); 574 firstRoot.appendChild( doc.createTextNode( "\n\n" ) ); 575 } 576 } 577 578 DomParser.write( new File(xmlFilename), doc ); 579 580 reload(); // 5.6.7.0 (2013/07/27) DBIDの属性情報のリストを更新後、初期化します。 581 } 582 583 /** 584 * DBドライバーの属性キーを返します。 585 * 586 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 587 * 588 * @return DBドライバーの属性キー 589 * @og.rtnNotNull 590 */ 591 public static String getDriverKey() { 592 return DBDRIVER_CLASS_KEY; 593 } 594 595 /** 596 * DBドライバーのリスト(配列)を返します。 597 * 598 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 599 * @og.rev 5.6.7.0 (2013/07/27) driverList を書き込むのではなく、作成します。 600 * 601 * @return DBドライバーリスト(配列) 602 * @og.rtnNotNull 603 */ 604 public String[] getDriverList() { 605 return driverList.toArray( new String[driverList.size()] ); 606 607 } 608 609 /** 610 * DBドライバーのリスト(配列)をセットします。 611 * 612 * このメソッドを呼び出すと、DBConfig.xmlで定義されているclass一覧を"一旦削除し"、 613 * その上で、引数のDBドライバー一覧をDBConfig.xmlに書き込みます。 614 * 615 * 書き込みの直前に、同じフォルダにタイムスタンプを付加したバックアップファイルを作成します。 616 * 617 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 618 * @og.rev 5.6.7.0 (2013/07/27) DBドライバーのリストを更新後、初期化します。 619 * 620 * @param drivers DBドライバーの配列(可変長引数) 621 */ 622 public void setDriverList( final String... drivers ) { 623 FileUtil.copy( xmlFilename, xmlFilename + "_" + System.currentTimeMillis() ); 624 625 final Document doc = DomParser.read( new File(xmlFilename) ); 626 final Element firstRoot = doc.getDocumentElement(); 627 628 final Element parent = (Element)firstRoot.getElementsByTagName( "dbDriver" ).item( 0 ); 629 deleteChildElements( parent, "class" ); 630 631 // 6.1.1.0 (2015/01/17) 可変長引数でもnullは来る。 632 if( drivers != null && drivers.length > 0 ) { 633 for( int i=0; i<drivers.length; i++ ) { 634 final Element newEle = doc.createElement( "class" ); 635 newEle.setTextContent( drivers[i] ); 636 parent.appendChild( newEle ); 637 } 638 } 639 640 DomParser.write( new File(xmlFilename), doc ); 641 642 reload(); // 5.6.7.0 (2013/07/27) DBドライバーのリストを更新後、初期化します。 643 } 644 645 /** 646 * DBID情報のキーとタイトルから、プルダウンメニューを作成するための情報を取得します。 647 * 648 * このメソッドを呼び出すと、DBConfig.xmlで定義されている dbidKey と、 title 属性から、 649 * 「key1:val1 key2:val2 ・・・」という文字列を作成します。 650 * これを利用すれば、プルダウンメニューが簡単に作成できます。 651 * 652 * @og.rev 5.6.7.0 (2013/07/27) プルダウンメニュー用の情報を作成します。 653 * @og.rev 5.6.7.1 (2013/08/09) 表題(title)属性のスペース対策 654 * @og.rev 6.2.6.0 (2015/06/19) 表題(title)属性のスペース対策(KEY:LBL をダブルクオートで囲う) 655 * @og.rev 6.3.9.0 (2015/11/06) Use block level rather than method level synchronization.(PMD) 656 * 657 * @return プルダウンメニューを作成するための情報 658 */ 659 public String getCodeKeyVal() { 660 if( codeKeyVal == null ) { 661 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE ); 662 // 6.3.9.0 (2015/11/06) 色々やりたいが、今はsynchronizedブロックにするだけにします。 663 synchronized( dbidMap ) { 664 for( final EDbid dbid : dbidMap.values() ) { 665 final String key = dbid.getDbidKey(); 666 final String lbl = StringUtil.nval( dbid.getTitle() , key ); 667 // 6.0.2.5 (2014/10/31) char を append する。 668 if( lbl.indexOf( ' ' ) >= 0 ) { // 5.6.7.1 (2013/08/09) スペース対策 669 buf.append( '"' ).append( key ).append( ':' ).append( lbl ).append( '"' ); 670 } 671 else { 672 buf.append( key ).append( ':' ).append( lbl ); 673 } 674 buf.append( ' ' ); 675 } 676 } 677 678 buf.setLength( buf.length()-1 ); // 最後のスペースを削除 679 codeKeyVal = buf.toString(); 680 } 681 682 return codeKeyVal; 683 } 684 685 /** 686 * 親要素を基点として、引数で指定されたタグ名を持つ子要素を削除します。 687 * 688 * @og.rev 5.6.7.0 (2013/07/27) staticメソッド を イスタンスメソッドに変更 689 * 690 * @param parent 親要素 691 * @param childTagName 削除する子要素のタグ名 692 */ 693 private void deleteChildElements( final Element parent, final String childTagName ) { 694 Node child = parent.getFirstChild(); 695 boolean isDel = false; 696 while( child != null ) { 697 // エレメント間の改行Cも削除するため、次の異なる要素が来るまでは削除し続けます。 698 if( child.getNodeType() == Node.ELEMENT_NODE ) { 699 // 6.4.4.1 (2016/03/18) 700 isDel = ((Element)child).getTagName().equalsIgnoreCase( childTagName ); 701 } 702 703 final Node next = child.getNextSibling(); 704 if( isDel ) { 705 parent.removeChild( child ); 706 } 707 child = next; 708 } 709 } 710}