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.sql.DatabaseMetaData;
019import java.sql.SQLException;
020import java.util.Locale;
021import java.util.Properties;
022import static org.opengion.fukurou.system.HybsConst.CR;                         // 6.1.0.0 (2014/12/26) refactoring
023import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE;      // 6.1.0.0 (2014/12/26) refactoring
024import org.opengion.fukurou.system.OgRuntimeException ;         // 6.4.2.0 (2016/01/29)
025
026/**
027 * JAXBで自動生成されたDBIDクラスを拡張したクラスです。
028 * (継承しているわけではない)
029 * <BR>
030 * 以下の属性が追加されています。<BR>
031 * dbProductName<BR>
032 * dbProductVersion<BR>
033 * driverName<BR>
034 * driverVersion<BR>
035 *
036 * @og.rev 4.0.0.0 (2007/10/25) 新規作成
037 * @og.rev 5.1.7.0 (2010/06/01) メソッドの修正、Cloneable の追加(浅いコピー)
038 * @og.rev 5.6.6.0 (2013/07/05) 表題(title)属性を追加
039 *
040 * @version  4.0
041 * @author       高橋正和
042 * @since        JDK5.0,
043 */
044public class EDbid implements Cloneable {
045
046        private         String  dbidKey                 = "DEFAULT";
047        private         String  title                   ;                                               // 5.6.6.0 (2013/07/05) 表題(title)属性を追加
048        private         String  url                             ;
049        private         String  user                    ;
050        private         String  password                = "";                                   // 5.7.2.0 (2014/01/10) パスワードは空文字を初期値とする。
051        private         boolean readonly                ;
052        private         int             mincount                = 3;
053        private         int             maxcount                = 30;
054        private         int             pooltime                = 3000;         // (秒数)
055        private         boolean isUseAppInfo    = true;
056        private         boolean isParamMetaData ;                                               // 5.3.8.0 (2011/08/01)
057
058        private         String  dbProductName   ;
059        private         String  dbProductVersion;
060        private         String  driverName              ;
061        private         String  driverVersion   ;
062
063        /* 5.5.2.0 (2012/05/01) DBConfigでpropertiesの指定を可能にします */
064        private final Properties props = new Properties();
065
066        /**
067         * デフォルトコンストラクター
068         *
069         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
070         */
071        public EDbid() { super(); }             // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
072
073        /**
074         * dbidKeyの取得
075         *
076         * 内部的には、大文字のみで管理します。
077         *
078         * @return      dbidキー
079         */
080        public String getDbidKey() {
081                return dbidKey;
082        }
083
084        /**
085         * dbidキーの設定
086         *
087         * 引数が、null でなく、ゼロ文字列でもない場合のみ、セットします。
088         * 内部的には、大文字のみで管理します。
089         *
090         * @og.rev 4.1.0.1 (2008/01/21) 登録時に、大文字に変換する。
091         *
092         * @param value 接続先ID
093         */
094        protected void setDbidKey( final String value ) {
095                if( isNotNull( value ) ) { dbidKey = value.toUpperCase( Locale.JAPAN ); }
096        }
097
098        /**
099         * 表題(title)属性の取得
100         *
101         * この、dbidKey を表す表題を取得します。ラベル(名前)のようなものです。
102         *
103         * @og.rev 5.6.6.0 (2013/07/05) 新規追加
104         *
105         * @return      表題(title)
106         */
107        public String getTitle() {
108                return title;
109        }
110
111        /**
112         * 表題(title)の設定
113         *
114         * 引数が、null でなく、ゼロ文字列でもない場合のみ、セットします。
115         *
116         * @og.rev 5.6.6.0 (2013/07/05) 新規追加
117         * @og.rev 5.6.8.0 (2013/09/06) title が未設定の時は、dbidKey をセットしておきます。
118         *
119         * @param value 表題(title)
120         */
121        protected void setTitle( final String value ) {
122                if( isNotNull( value ) ) { title = value; }
123                else                                     { title = dbidKey; }           // 5.6.8.0 (2013/09/06)
124        }
125
126        /**
127         * URLの取得。
128         *
129         * @return      URL
130         */
131        public String getUrl() {
132                return url;
133        }
134
135        /**
136         * URLの設定
137         * 引数が、null でなく、ゼロ文字列でもない場合のみ、セットします。
138         *
139         * @param value URL文字列
140         */
141        protected void setUrl( final String value ) {
142                if( isNotNull( value ) ) { url = value; }
143        }
144
145        /**
146         * ユーザーの取得。
147         *
148         * @return      ユーザー
149         */
150        public String getUser() {
151                return user;
152        }
153
154        /**
155         * userの設定
156         * 引数が、null でなく、ゼロ文字列でもない場合のみ、セットします。
157         *
158         * @param value user文字列
159         */
160        protected void setUser( final String value ) {
161                if( isNotNull( value ) ) { user = value; }
162        }
163
164        /**
165         * パスワードの取得。
166         *
167         * @return      パスワード
168         */
169        public String getPassword() {
170                return password;
171        }
172
173        /**
174         * パスワードの設定
175         * 引数が、null でなく、ゼロ文字列でもない場合のみ、セットします。
176         *
177         * @param value パスワード文字列
178         */
179        protected void setPassword( final String value ) {
180                if( isNotNull( value ) ) { password = value; }
181        }
182
183        /**
184         * readonlyの取得。
185         *
186         * @return      [true:読み取り専用/false:通常]
187         */
188        public boolean isReadonly() {
189                return readonly ;
190        }
191
192        /**
193         * readonlyの設定
194         * 引数が、null でなく、ゼロ文字列でもない場合のみ、セットします。
195         *
196         * @param value  readonly文字列 [true/false]
197         */
198        protected void setReadonly( final String value ) {
199                if( isNotNull( value ) ) { readonly = Boolean.parseBoolean( value ); }          // 6.1.0.0 (2014/12/26) refactoring
200        }
201
202        /**
203         * 最小数の取得。
204         *
205         * @return      最小数
206         */
207        public int getMincount() {
208                return mincount;
209        }
210
211        /**
212         * 最小数の設定
213         * 引数が、null でなく、ゼロ文字列でもない場合のみ、セットします。
214         *
215         * @param value 最小数(数字タイプ文字列)
216         */
217        protected void setMincount( final String value ) {
218                if( isNotNull( value ) ) { mincount = Integer.parseInt( value ); }              // 6.0.2.4 (2014/10/17) メソッド間違い
219        }
220
221        /**
222         * 最大数の取得。
223         *
224         * @return      最大数
225         */
226        public int getMaxcount() {
227                return maxcount;
228        }
229
230        /**
231         * 最大数の設定
232         * 引数が、null でなく、ゼロ文字列でもない場合のみ、セットします。
233         *
234         * @param value 最大数(数字タイプ文字列)
235         */
236        protected void setMaxcount( final String value ) {
237                if( isNotNull( value ) ) { maxcount = Integer.parseInt( value ); }              // 6.0.2.4 (2014/10/17) メソッド間違い
238        }
239
240        /**
241         * プールに保管して置く時間(秒数)の取得。
242         *
243         * @return      プールに保管する時間(秒数)
244         */
245        public int getPooltime() {
246                return pooltime;
247        }
248
249        /**
250         * プールに保管して置く時間(秒数))の設定
251         * 引数が、null でなく、ゼロ文字列でもない場合のみ、セットします。
252         *
253         * @param value プールに保管して置く時間(秒数)(数字タイプ文字列)
254         */
255        protected void setPooltime( final String value ) {
256                if( isNotNull( value ) ) { pooltime = Integer.parseInt( value ); }              // 6.0.2.4 (2014/10/17) メソッド間違い
257        }
258
259        /**
260         * ApplicationInfoオブジェクトを使用するかどうか[true/false]の情報を取得。
261         *
262         * @return      使用するかどうか
263         */
264        public boolean isApplicationInfo() {
265                return isUseAppInfo ;
266        }
267
268        /**
269         * ApplicationInfoオブジェクトを使用するかどうか[true/false]の情報を設定
270         * 引数が、null でなく、ゼロ文字列でもない場合のみ、セットします。
271         *
272         * @param value ApplicationInfoオブジェクトを使用するかどうか [true/false]
273         */
274        protected void setApplicationInfo( final String value ) {
275                if( isNotNull( value ) ) { isUseAppInfo = Boolean.parseBoolean( value ); }      // 6.1.0.0 (2014/12/26) refactoring
276        }
277
278        /**
279         * メタデータを受け取って dbProductName,dbProductVersion,driverName,driverVersion を一括で設定します。
280         *
281         * @og.rev 4.0.0.0 (2007/10/30) 保持情報オブジェクト化に伴う変更
282         * @og.rev 5.3.8.0 (2011/08/01) postgreSQL時のカラムタイプ判定の必要有無(ApplicationInfo.useParameterMetaData)
283         * @og.rev 6.4.9.5 (2016/09/09) DERBY も、isParamMetaData=true を返します。
284         * @og.rev 8.0.0.0 (2021/09/30) FIREBIRD も、isParamMetaData=true を返します。
285         *
286         * @param meta メタデータオブジェクト
287         * @throws SQLException データベースアクセスエラー
288         */
289        public void setMetaDataInfo( final DatabaseMetaData meta ) throws SQLException {
290                dbProductName   = meta.getDatabaseProductName() ;
291                dbProductVersion= meta.getDatabaseProductVersion() ;
292                driverName              = meta.getDriverName() ;
293                driverVersion   = meta.getDriverVersion() ;
294
295                // dbProductName は、大文字にしておいても問題は無いが、今は影響範囲を小さくしておきます。
296                final String dbName = dbProductName.toUpperCase( Locale.JAPAN );                // 6.4.9.5 (2016/09/09) 大文字化します。
297
298                isUseAppInfo    = isUseAppInfo && "ORACLE".equalsIgnoreCase( dbProductName ) ;
299                isParamMetaData = dbName.contains( "POSTGRES" )
300                                                || dbName.contains( "FIREBIRD" )                                                // 8.0.0.0 (2021/09/30)
301                                                || dbName.contains( "DERBY" );                                                  // 6.4.9.5 (2016/09/09)
302        }
303
304        /**
305         * DBプロダクト名の取得。
306         *
307         * @return      DBプロダクト名
308         */
309        public String getDbProductName() {
310                return dbProductName;
311        }
312
313        /**
314         * DBプロダクト・バージョンの取得。
315         *
316         * @return      DBプロダクト・バージョン
317         */
318        public String getDbProductVersion() {
319                return dbProductVersion;
320        }
321
322        /**
323         * ドライバー名の取得。
324         *
325         * @return      ドライバー名
326         */
327        public String getDriverName() {
328                return driverName;
329        }
330
331        /**
332         * ドライバーのバージョンの取得。
333         *
334         * @return      ドライバーのバージョン
335         */
336        public String getDriverVersion() {
337                return driverVersion;
338        }
339
340        /**
341         * ParamMetaData を利用するかどうか[true/false]を返します。
342         *
343         * これは、PostgreSQL の時は、trueになります。
344         *
345         * @og.rev 5.3.8.0 (2011/08/01) 新規追加
346         *
347         * @return      利用するかどうか[true/false]
348         */
349        public boolean useParamMetaData() {
350                return isParamMetaData ;
351        }
352
353        /**
354         * propMapへの追加。
355         *
356         * @og.rev 5.5.2.0 (2012/05/01) 新規追加
357         * @param key プロパティのキー
358         * @param val ポロパティの値
359         */
360        protected void addProp( final String key, final String val ) {
361                props.put ( key, val );
362        }
363
364        /**
365         * propMapへの追加。
366         * 最初の=でkeyとvalueを分割する
367         *
368         * @og.rev 5.5.2.0 (2012/05/01) 新規追加
369         * @og.rev 5.5.2.1 (2012/05/07) propsへの追加漏れ、カンマを=に変更
370         * @param prop プロパティのキーと値の組み合わせ
371         */
372        protected void addProp( final String prop ) {
373                if( prop!=null && prop.indexOf( '=' ) > 0 ){
374                        final String key = prop.substring( 0 , prop.indexOf('=') );
375                        final String val = prop.substring( prop.indexOf('=') + 1 );
376                        addProp( key, val ); // 5.5.2.1 (2012/05/07)
377                }
378        }
379
380        /**
381         * propMapの取得。
382         *
383         * @og.rev 5.5.2.0 (2012/05/01) 新規追加
384         * @og.rev 6.3.9.0 (2015/11/06) 内部Propertiesオブジェクトではなく、複製して返します。
385         *
386         * @return 複製Propertiesオブジェクト
387         */
388        public Properties getProps(){
389                return new Properties( props );                 // 6.3.9.0 (2015/11/06)
390        }
391
392        /**
393         * 文字列がnullでも空文字列でもないかどうかを評価します。
394         *
395         * スペース文字は、trim() してから、!isEmpty() で判断しますので、false になります。
396         *
397         * @og.rev 5.1.7.0 (2010/06/01) 新規作成
398         *
399         * @param value 評価する文字列
400         *
401         * @return 結果(true:nullでも空文字列でもない)
402         */
403        private boolean isNotNull( final String value ) {
404                return value != null && !value.trim().isEmpty() ;                       // 6.0.2.5 (2014/10/31) refactoring
405        }
406
407        /**
408         * 自分自身の clone を返します。
409         *
410         * Cloneable の実装で、内部的には、Object クラスの clone メソッドを読んでいます。
411         *
412         * @og.rev 5.1.7.0 (2010/06/01) 新規作成
413         *
414         * @return      自分自身の clone を返します。
415         * @throws      RuntimeException clone が失敗しました場合
416         * @og.rtnNotNull
417         */
418        @Override
419        public EDbid clone() {
420                try {
421                        return (EDbid)super.clone() ;
422                }
423                catch( final CloneNotSupportedException ex ) {
424                        final String errMsg = "clone が失敗しました。"
425                                                                + ex.getMessage() ;
426                        throw new OgRuntimeException( errMsg,ex );
427                }
428        }
429
430        /**
431         * 自分自身の clone を返します。
432         *
433         * ここでは、dbidKey を指定した、clone() を作成します。
434         * Titleも、指定した、dbidKey をセットしておきます。
435         *
436         * @og.rev 6.4.3.4 (2016/03/11) 新規作成
437         *
438         * @param id 接続先ID
439         * @return      dbidKeyを指定して、自分自身のcloneを返します。
440         * @og.rtnNotNull
441         */
442        public EDbid clone( final String id ) {
443                final EDbid obj = this.clone();
444                obj.setDbidKey( id );
445                obj.setTitle( id );
446
447                return obj;
448        }
449
450        /**
451         * 簡易な内部情報の文字列化します。
452         *
453         * @og.rev 5.3.4.0 (2011/04/01) toString() の簡易版
454         * @og.rev 5.5.2.1 (2012/05/07) properties情報を出力するようにする
455         * @og.rev 5.6.6.0 (2013/07/05) 表題(title)属性を追加
456         *
457         * @return 内部情報の文字列
458         * @og.rtnNotNull
459         */
460        public String info() {
461                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE )
462                        .append( "DBID=["  ).append( dbidKey ).append( "] , " )
463                        .append( "TITLE=[" ).append( title   ).append( "] , " )                 // 5.6.6.0 (2013/07/05) 表題(title)属性を追加
464                        .append( "URL=["   ).append( url     ).append( "] , " )
465                        .append( "USER=["  ).append( user    ).append( ']'  )
466                        .append( CR )
467                        .append( "DB Product=[" ).append( dbProductName )
468                        .append( '(' ).append( dbProductVersion ).append( ')' ).append( ']' )
469                        .append( CR )
470                        .append( "DB Driver =[" ).append( driverName )
471                        .append( '(' ).append( driverVersion ).append( ')' ).append( ']' )
472                        .append( CR )
473                        .append( "PROPERTIES=[" ).append( props.toString() ).append( ']' ) // 5.5.2.1 (2012/05/07)
474                        .append( CR );
475                return buf.toString();
476        }
477
478        /**
479         * 内部情報を文字列化します。
480         *
481         * @og.rev 5.3.4.0 (2011/04/01) info() メソッドを利用するように変更
482         *
483         * @return      内部情報の文字列
484         * @og.rtnNotNull
485         */
486        @Override
487        public String toString() {
488                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE )
489                        .append( info() )
490                //      .append( "DBID=[" ).append( dbidKey ).append( "]," )
491                //      .append( "URL =[" ).append( url     ).append( "]," )
492                //      .append( "USER=[" ).append( user    ).append( "]," )
493                //      .append( CR )
494                //      .append( "DB Product=[" ).append( dbProductName )
495                //      .append( "(" ).append( dbProductVersion ).append( ")" ).append( "]" )
496                //      .append( CR )
497                //      .append( "DB Driver =[" ).append( driverName )
498                //      .append( "(" ).append( driverVersion ).append( ")" ).append( "]" )
499                //      .append( CR )
500                        .append( "MINCOUNT=[" ).append( mincount ).append( "]," )
501                        .append( "MAXCOUNT=[" ).append( maxcount ).append( "]," )
502                        .append( "POOLTIME=[" ).append( pooltime ).append( "]," )
503                        .append( "READONLY=[" ).append( readonly ).append( "]," )
504                        .append( "APPINFO =[" ).append( isUseAppInfo ).append( ']' )            // 6.0.2.5 (2014/10/31) char を append する。
505                        .append( CR );
506                return buf.toString();
507        }
508}