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.common;
017
018import java.io.File;                                                    // 5.7.3.2 (2014/02/28) Tomcat8 対応
019import java.io.IOException;
020import java.io.PrintWriter;
021import java.io.UnsupportedEncodingException;
022import java.lang.reflect.Field;
023import java.lang.reflect.Modifier;
024import java.net.MalformedURLException;
025import java.net.URL;
026import java.sql.Connection;
027import java.sql.PreparedStatement;
028import java.sql.ResultSet;
029import java.sql.SQLException;
030import java.util.ArrayList;
031import java.util.Date;
032import java.util.Enumeration;
033import java.util.HashMap;
034import java.util.LinkedHashMap;
035import java.util.List;
036import java.util.Locale;
037import java.util.Map;
038import java.util.Set;
039import java.util.TreeMap;
040
041import javax.servlet.ServletContext;
042
043import org.opengion.fukurou.db.ConnectionFactory;
044import org.opengion.fukurou.util.Closer;
045import org.opengion.fukurou.util.FindClassFiles;
046import org.opengion.fukurou.util.LogWriter;
047import org.opengion.fukurou.util.StringUtil;
048
049/**
050 * ログインしたサーブレットコンテキストに対応したシステムパラメータデータを取得するクラスです。
051 *
052 * システムパラメータデータ(GE12)は、パラメータ(PARAM_ID)に対して、各種設定値(PARAM)を
053 * 持っています。
054 * 従来は、resource.システムパラメータ の一般設定用の システムパラメータ ファイルと
055 * エンジン内部で持っている org/hsgw/hayabusa/resource/properties の
056 * システムパラメータ ファイルにより維持されていましたが、システムパラメータ
057 * 定義テーブル(GE12)と、commom/SystemData.java クラスによる管理に変更されました。
058 *
059 * システムパラメータは、DBへのアクセスを決定するため、初期設定値を定義する必要があります。
060 * これは、、アプリケーション・ディスクリプタ(WEB-INF/web.xml)に、context-param として、
061 * キーと値のセットで、初期アクセス用の情報を渡します。
062 * システムパラメータ定義テーブル(GE12)には、SYSTEM_IDとして、通常のシステムIDと、
063 * エンジンパラメータがあります。エンジンパラメータは、SYSTEM_ID='**'として、登録
064 * されています。
065 *
066 * <table border="1" frame="box" rules="all" >
067 *   <caption>システムパラメータの説明</caption>
068 *   <tr><th>種類        </th><th>SYSTEM_ID</th><th>作成区分</th><th>説明</th></tr>
069 *   <tr><td>エンジン共通</td><td>**  </td><td>0:エンジン</td><td>エンジン共通で定義しているパラメータ                     </td></tr>
070 *   <tr><td>エンジン個別</td><td>個別  </td><td>0:エンジン</td><td>システム毎にエンジンが登録しているパラメータ </td></tr>
071 *   <tr><td>システム共通</td><td>**  </td><td>1:システム     </td><td>システム毎にエンジンが登録しているパラメータ     </td></tr>
072 *   <tr><td>システム個別</td><td>個別  </td><td>1:システム     </td><td>システム毎に各自が独自に登録しているパラメータ    </td></tr>
073 * </table>
074 *
075 * <table border="1" frame="box" rules="all" >
076 *   <caption>アプリケーション・ディスクリプタ(WEB-INF/web.xml)設定情報</caption>
077 *   <tr><th>パラメータ  </th><th>設定値例                               </th><th>解説                                 </th></tr>
078 *   <tr><td>SYSTEM_ID      </td><td>GE                                         </td><td>このアプリケーションのシステムID </td></tr>
079 *   <tr><td>TOMCAT_PORT</td><td>8823                                   </td><td>Tomcat起動時ポート番号    </td></tr>
080 *   <tr><td>LOG_FILE       </td><td>log/log_$(yyyyMMdd).txt</td><td>JSPアクセスログ出力先          </td></tr>
081 * </table>
082 *
083 * ※ 5.6.7.0 (2013/07/27)
084 *    InitFileLoader により、特定のクラスパス内の 拡張XDK 形式の xml ファイル を処理します。
085 *    クラスパスが、"/resource" 以下のすべての xml ファイルは、DBIDが RESOURCE の接続先に対して処理されます。
086 *    クラスパスが、"/xml" 以下のすべての xml ファイルは、DBIDが DEFAULT の接続先に対して処理されます。
087 *    各クラスパス以下のファイルは、実フォルダでも、jar形式に圧縮された形式でも処理されます。
088 *
089 * @og.rev 4.0.0.0 (2005/01/31) 新規作成
090 * @og.rev 4.0.0.0 (2007/10/26) loadDBResourceのコネクションをFactoryから取るように変更
091 * @og.group 初期化
092 *
093 * @version  4.0
094 * @author   Kazuhiko Hasegawa
095 * @since    JDK5.0,
096 */
097public final class SystemParameter {
098
099        /**
100         *      デフォルトコンストラクターをprivateにして、
101         *      オブジェクトの生成をさせないようにする。
102         *
103         */
104        private SystemParameter() {}
105
106        /** plugin クラスの取得用クラスパス指定       {@value}        */
107        public static final String PLUGIN = "org/opengion/plugin";
108
109        /** システム共通/個別パラメータ(SYSTEM_ID in ('**',?) KBSAKU != '0')の一括読込のクエリー       {@value}        */
110//      public static final String QUERY = "SELECT PARAM_ID,PARAM,FGCRYPT"
111//                                                                      + " FROM GE12 WHERE SYSTEM_ID IN (?,'**')"
112//                                                                      + " AND ( CONTXT_PATH IS NULL OR CONTXT_PATH = ?)"
113//                                                                      + " AND FGJ='1' AND KBSAKU != '0'"
114//                                                                      + " ORDER BY SYSTEM_ID,CONTXT_PATH DESC,KBSAKU,SEQNO" ;
115        // 4.0.0.0 (2007/10/05) CONTXT_PATH に、DEFAULT '**' NOT NULL 制約を付ける。
116        /** システム共通/個別パラメータ(SYSTEM_ID in ('**',?) and KBSAKU &gt; '0')の一括読込のクエリー     {@value}        */
117        public static final String QUERY = "SELECT PARAM_ID,PARAM,FGCRYPT"
118                                                                        + " FROM GE12 WHERE SYSTEM_ID IN (?,'**')"
119                                                                        + " AND CONTXT_PATH IN (?,'**')"
120                                                                        + " AND FGJ='1' AND KBSAKU > '0'"
121                                                                        + " ORDER BY SYSTEM_ID,CONTXT_PATH,FGJ,KBSAKU,SEQNO" ;
122
123        /** システム共通/個別パラメータ(SYSTEM_ID in ('**',?) and KBSAKU &gt; '0')の一括登録のクエリー     {@value}        */
124        public static final String INS_SYS = "INSERT INTO GE12"
125                                                                        + " ( SYSTEM_ID,CONTXT_PATH,PARAM_ID,SEQNO,PARAM,TITLE,CONTENTS,PARAM_LVL,FGJ,KBSAKU )"
126                                                                        + " SELECT"
127                                                                        + " ?,?,?,?,?,TITLE,CONTENTS,PARAM_LVL,'1','0'"
128                                                                        + " FROM GE12 WHERE SYSTEM_ID='**' AND FGJ='1' AND KBSAKU='0' AND PARAM_ID=?" ;
129
130        /** エンジン個別(SYSTEM_ID='個別' KBSAKU='0'  CONTXT_PATH='自身')パラメータの一括削除のクエリー  {@value}        */
131        public static final String DEL_SYS = "DELETE FROM GE12 WHERE SYSTEM_ID=? AND KBSAKU='0' AND CONTXT_PATH=?";
132
133        /** システムパラメータ構築中のエラーをセットしていきます。 */
134        private static final List<String> errMsgList = new ArrayList<String>();
135
136        /**
137         * コンテキスト毎に システムパラメータオブジェクトを作成します。
138         * このクラスのスタートポイントメソッドになります。
139         *
140         * @og.rev 4.1.0.1 (2008/01/23) ログ出力先の変更(全てLogWriter経由で出力)
141         * @og.rev 5.5.4.4 (2012/07/20) LogWriter.log 追加
142         * @og.rev 5.5.4.4 (2012/07/20) SQLException は、catch しているので、loadDBResource からは、throws されない。
143         * @og.rev 5.7.2.0 (2014/01/10) Throwable の情報をもう少し詳細に出します。
144         * @og.rev 5.10.17.2 (2019/11/22) コンテキスト名の取得対応
145         *
146         * @param context Servletコンテキスト
147         *
148         * @return      システムパラメータのマップ
149         */
150        public static Map<String,String> makeSystemParameter( final ServletContext context ) {
151                // 4.1.0.1 (2008/01/23) ログ出力は全てLogWriterで行うため、廃止
152//              try {
153//                      String file = context.getInitParameter( "LOG_FILE" );
154//                      if( file != null ) {
155//                              // 日付フォームのファイル名を変換します。
156//                              DateSet dateSet = new DateSet();
157//                              file = dateSet.changeString( file );
158//                              // 4.1.0.0 (2008/01/12) 絶対パスでない場合は連結
159//                              if( ! new File( file ).isAbsolute() ) {
160//                                      String path = context.getRealPath( "/" );
161//                                      file = path + file;
162//                              }
163//
164//                              // append モードで自動フラッシュON
165//                              System.setErr( new PrintStream( new FileOutputStream( file,true ),true ) );
166//                      }
167//              }
168//              catch( FileNotFoundException ex ) {
169//                      LogWriter.log( "web.xml InitParameter \"LOG_FILE\" is abusion." );
170//                      LogWriter.log( ex.getMessage() );
171//              }
172
173                errMsgList.clear() ;    // 呼び出し都度、エラーリストをクリアします。
174
175                Map<String,String> engParam = null;
176                Map<String,String> sysParam = null;
177                try {
178                        String contextName = getContextName( context );
179
180                        System.out.println( "Context Initialized [" + contextName + "]  " + new Date() );
181                        System.out.print( "  Version [" + BuildNumber.VERSION_NO + " " );
182                        System.out.print( BuildNumber.BUILD_TYPE );
183                        System.out.println( "]" );
184
185                        // システムデータクラスより、エンジンパラメータ情報を初期設定します。
186                        // エンジンパラメータは、SystemData クラスの public static メンバーです。
187                        engParam = loadParameter( SystemData.class );
188
189                        // コンテキストより取得できるシステムパラメータ情報を取得します。
190                        // web.xml で設定したパラメータを取得します。
191                        // SYSTEM_ID,DB_DRIVER,DB_URL などは、loadDBResource で使用します。
192                        sysParam = loadInitialParameter( context,contextName );
193
194                        // 5.10.17.2 (2019/11/22) ADD コンテキストディレクトリ名
195                        sysParam.put("CONTEXT_DIRNM", getContextDirNm(context));
196
197                        // システム個別に設定される、エンジン起動時情報を初期設定します。
198                        // エンジン起動時情報は、BuildNumber クラスの public static メンバーです。
199                        sysParam.putAll( loadParameter( BuildNumber.class ) );
200                        sysParam.putAll( loadParameter( PLUGIN ) );
201
202                        // GE12 データベースより読み取ります。
203                        // 引数のMapに読み込んだ値を追加した Map を返します。
204                        // つまり、システムパラメータ情報の上書きを行います。
205                        // 5.5.4.4 (2012/07/20) SQLException は、catch しているので、loadDBResource からは、throws されない。
206        //              try {
207                                sysParam = loadDBResource( sysParam );
208        //              }
209        //              catch( SQLException ex ) {
210        //                      String errMsg = "DB終了(close)処理を実行できませんでした。" + HybsSystem.CR
211        //                                              + ex.getMessage() + ":" + ex.getSQLState() ;
212        //                      LogWriter.log( ex );                                    // 5.5.4.4 (2012/07/20) LogWriter.log 追加
213        //                      errMsgList.add( errMsg );
214        //              }
215                }
216                catch( Throwable th ) {         // 3.6.1.0 (2005/01/05)
217                        LogWriter.log( th );                                            // 5.5.4.4 (2012/07/20) LogWriter.log 追加
218                        // 5.7.2.0 (2014/01/10) Throwable の情報をもう少し詳細に出します。
219//                      errMsgList.add( th.getMessage() );
220                        String errMsg = "処理を実行できませんでした。"        + HybsSystem.CR
221                                                + th.getMessage()                                               + HybsSystem.CR
222                                                + StringUtil.ogStackTrace( th ) ;
223                        errMsgList.add( errMsg );
224                }
225                finally {
226                        // 初期値のエンジンパラメータに個別のシステムパラメータを追加設定します。
227                        // つまり、エンジンパラメータ情報に上書きを行います。
228                        if( engParam != null ) {
229                                engParam.putAll( sysParam );
230                        }
231                        else {
232                                engParam = new HashMap<String,String>();
233                        }
234
235                        int errCnt = errMsgList.size();
236                        if( errCnt > 0 ) {
237                                StringBuilder buf = new StringBuilder();
238                                buf.append( "【システムパラメータの初期化に失敗しました。】" );
239                                buf.append( HybsSystem.CR );
240                                buf.append( "Tomcat の設定状況をご確認ください。" );
241                                buf.append( HybsSystem.CR );
242                                buf.append( "========================================" );
243                                buf.append( HybsSystem.CR );
244
245                                for( int i=0; i<errCnt; i++ ) {
246                                        buf.append( errMsgList.get(i) );
247                                        buf.append( HybsSystem.CR );
248                                        buf.append( "----------------------------------------" );
249                                        buf.append( HybsSystem.CR );
250                                }
251                                System.out.println( buf );
252                                engParam.put( HybsSystem.LOCAL_CONTX_ERR_KEY,buf.toString() );
253                        }
254                }
255                return engParam ;
256        }
257
258        /**
259         * コンテキストより、アプリケーション設定情報を取得します。
260         * 初期値は、アプリケーション・ディスクリプタ(WEB-INF/web.xml)に
261         * context-param として、キーと値のセットで、初期アクセス用の情報を渡します。
262         * データベースへの接続は、WEB-INF の DBConfig.xml で設定された情報を使用します。
263         *
264         * ここでは、各コンテキスト毎の内部情報を取得します。その中には、
265         * BuildNumber クラスで定義されている各種フィールド属性も含まれます。
266         *
267         * REAL_PATH       : アドレス(/)に対する、実ディレクトリパス
268         * CONTEXT_NAME    : アクセス先の仮想フォルダ名(URLのコンテキスト名)
269         * JSP             : アクセス先のJSPフォルダ名(/URLのコンテキスト名/jsp)
270         * SYSTEM_ID       : web.xml で指定する、SYSTEM_ID       の設定値
271         * TOMCAT_PORT     : web.xml で指定する、Tomcat起動時ポート番号(8823)
272         * LOG_FILE        : web.xml で指定する、JSPアクセスログ出力先(log/log_$(yyyyMMdd).txt)
273         * SERVER_INFO     : サーバー情報     [例: HN50G5 ( 200.1.50.165 ) ]
274         * SERVLET_INFO    : サーブレット情報 [例: Apache Tomcat/5.5.9     ]
275         * TOMCAT_WORK     : Tomcatワークの位置 [例: H:\java\tomcat5.5.17\work\Catalina\localhost\ver4  ]
276         * TOMCAT_HOME     : Tomcat環境の位置   [例: H:\java\tomcat5.5.17  ]
277         * JAVA_HOME       : Java実行環境の位置 [例: H:\java\jdk150\jre ]
278         * ENGINE_INFO     : バージョン番号 [例: 4.3.6.6 ]
279         *
280         * RESOURCE_DBID   : "RESOURCE" 固定値を設定。WEB-INF/web.xml で指定しても無効です。
281         *
282         * @og.rev 4.1.0.0 (2007/12/27) web.xmlからTOMCAT_PORTを読む処理を追加
283         * @og.rev 4.2.0.0 (2008/02/18) TOMCAT_PORTを環境変数から取得するよう変更
284         * @og.rev 4.2.0.0 (2008/02/20) web.xmlでSYSTEM_IDが空白の場合に大文字コンテキスト名が設定されるよう変更
285         * @og.rev 4.3.6.6 (2009/05/15) コンテキスト単位にエンジンバージョン情報を持つ(バージョンアップ判定用)
286         * @og.rev 5.6.7.1 (2013/08/09) RESOURCE_DBID の値に、"RESOURCE" を設定しておきます。
287         * @og.rev 5.6.7.3 (2013/08/23) TOMCAT_HOME を追加
288         * @og.rev 5.7.3.2 (2014/02/28) Tomcat8 対応。getRealPath( "/" ) の互換性のための修正。
289         * @og.rev 5.10.20.2 (2020/03/05) RealPathの最後に\が付くJava8対応
290         *
291         * @param context Servletコンテキスト
292         * @param contextName コンテキスト名
293         *
294         * @return      システムパラメータのマップ
295         */
296        private static Map<String,String> loadInitialParameter( final ServletContext context,final String contextName ) {
297                Map<String,String> map = new LinkedHashMap<String,String>();
298
299                // コンテキストの初期化パラメータ他の情報を登録しておきます。
300                Enumeration<?> enume = context.getInitParameterNames() ;          // 4.3.3.6 (2008/11/15) Generics警告対応
301                while( enume.hasMoreElements() ) {
302                        String key = (String)enume.nextElement();
303                        String val = context.getInitParameter( key );
304                        if( val != null && val.length() == 0 ) { val = null; }
305                        map.put( key,val );
306                }
307
308                // SYSTEM_IDがnullの場合は大文字のコンテキスト名を設定
309                if( map.get( "SYSTEM_ID" ) == null ){ // 4.2.0.0 (2008/02/20)
310                        map.put( "SYSTEM_ID", contextName.toUpperCase( Locale.JAPAN ) );
311                }
312
313                // 各種システム情報を登録しておきます。
314//              map.put( "REAL_PATH"    ,context.getRealPath( "/" ) );
315                map.put( "REAL_PATH"    ,context.getRealPath( "" )  // 5.7.3.2 (2014/02/28) Tomcat8 対応
316                                + (context.getRealPath( "" ).endsWith(File.separator) ? "" : File.separator) ); // 5.10.20.2 (2020/03/06) Java8
317                map.put( "CONTEXT_NAME" ,contextName );
318                map.put( "JSP"                  ,"/" + contextName + "/jsp" );
319                map.put( "SERVLET_INFO" ,context.getServerInfo() );
320                map.put( "TOMCAT_WORK"  ,String.valueOf( context.getAttribute( "javax.servlet.context.tempdir" ) ) );
321                map.put( "TOMCAT_HOME"  ,System.getProperty( "catalina.home" ) );       // 5.6.7.3 (2013/08/23)
322                map.put( "JAVA_HOME"    ,System.getProperty( "java.home" ) );
323
324                map.put( "HOST_NAME"    ,HybsSystem.HOST_NAME  );
325                map.put( "HOST_ADRS"    ,HybsSystem.HOST_ADRS  );
326                map.put( "SERVER_INFO"  ,HybsSystem.HOST_NAME  + " ( " + HybsSystem.HOST_ADRS + " )" );
327                map.put( "ENGINE_INFO"  ,BuildNumber.ENGINE_INFO );
328                String TOMCAT_PORT = System.getenv( "CONNECTOR_PORT" ); // 4.2.0.0 (2008/02/18) ポート番号を環境変数から取得に変更
329                if( TOMCAT_PORT == null || TOMCAT_PORT.length() == 0 ) { // 互換性のためweb.xmlからの取得を残す
330                        TOMCAT_PORT = map.get( "TOMCAT_PORT" ); // 4.1.0.0 (2007/12/27)
331                }
332
333                String HOST_URL;
334                if( TOMCAT_PORT == null || TOMCAT_PORT.length() == 0 ) { // 両者とも値が取得できない場合は**
335                        HOST_URL = "**";
336                }
337                else {
338                        HOST_URL = HybsSystem.HOST_NAME + ":" + TOMCAT_PORT + "/" + contextName + "/";
339                }
340                map.put( "HOST_URL", HOST_URL );
341
342                // 5.6.7.1 (2013/08/09) RESOURCE_DBID の値に、"RESOURCE" を設定しておきます。
343                map.put( "RESOURCE_DBID", "RESOURCE" );
344
345                System.out.println( "    Load Initial Parameter [" + map.size() + "] finished." );
346                return map ;
347        }
348
349        /**
350         * アプリケーション個別に設定しているリソースDB(GE12)を取得します。
351         *
352         * データベースへの接続は、WEB-INF の DBConfig.xml で設定された情報を元に、
353         * org.opengion.fukurou.db.ConnectionFactory で接続先を取得します。
354         * ここでは、web.xml で定義された各アプリケーション個別のパラメ―タを取得します。
355         * SYSTEM_ID(必須) です。
356         *
357         * @og.rev 4.0.0.0 (2007/10/10) 接続先情報の管理見直し(コンテキスト初期設定)
358         * @og.rev 4.0.0.0 (2007/10/26) コネクションをファクトリーから取ってくるように変更
359         * @og.rev 4.3.6.5 (2009/05/08) dataパス内のXMLファイルも読み取るようにする
360         * @og.rev 4.3.6.6 (2009/05/15) ↑を廃止。自動インストール対応。
361         * @og.rev 5.1.2.0 (2010/01/01) connection.setAutoCommit は、ConnectionFactory で設定済みなので、コメントアウト
362         * @og.rev 5.1.9.0 (2010/08/01) 自動インストールの設定見直し(画面からのインストール対応)
363         * @og.rev 5.5.4.4 (2012/07/20) SQLException は、catch しているので、このメソッドからは、throws されない。
364         * @og.rev 5.5.4.5 (2012/07/27) 初期起動時のDB接続先は、RESOURCE_DBID とする。
365         * @og.rev 5.6.6.1 (2013/07/12) xml パス内のXMLファイルがあれば、DB登録します。
366         * @og.rev 5.6.7.0 (2013/07/27) InitFileLoader で、resource以下は、DBID=RESOURCE xml以下は、DBID=DEFAULT に登録します。
367         * @og.rev 5.6.7.3 (2013/08/23) DBID=RESOURCE 漏れ
368         * @og.rev 5.7.2.0 (2014/01/10) RuntimeException は、catch しないようにします。
369         * @og.rev 5.10.17.2 (2019/11/22) コンテキスト名の取得対応
370         *
371         * @param       sysParam        入力システムパラメータマップ
372         *
373         * @return      システムパラメータのマップ
374         */
375//      private static Map<String,String> loadDBResource( final Map<String,String> sysParam ) throws SQLException {
376        private static Map<String,String> loadDBResource( final Map<String,String> sysParam ) {
377                String SYSTEM_ID                = sysParam.get( "SYSTEM_ID" );
378                String CONTEXT_NAME             = sysParam.get( "CONTEXT_NAME" );       // コンテキスト別システムリソース
379                String HOST_URL                 = sysParam.get( "HOST_URL" );           // 4.1.0.0 (2007/12/21) TOMCATへのアクセス用
380                String RESOURCE_DBID    = sysParam.get( "RESOURCE_DBID" );      // 5.5.4.5 (2012/07/27) 初期起動時のDB接続先
381                String CONTEXT_DIRNM    = sysParam.get( "CONTEXT_DIRNM" );      // 5.10.17.2 (2019/11/22) コンテキストディレクトリ名
382
383                // 必須項目チェックを行います。SYSTEM_IDは必須です。
384                // これは、web.xml で定義が必要です。
385                // 4.0.0.0 (2007/10/23)接続情報XML化につきDB_URLチェックを削除
386                if( ( SYSTEM_ID == null || SYSTEM_ID.length() == 0 ) ) {
387                        String errMsg = "システムパラメータの必須項目(SYSTEM_ID,DB_URL)が null です。" + HybsSystem.CR
388                                                        + "SYSTEM_ID=[" + SYSTEM_ID + "] " + HybsSystem.CR
389                                                        + "Versino=[" + BuildNumber.VERSION_NO + "] " + HybsSystem.CR ;
390                        errMsgList.add( errMsg );
391                        return sysParam ;
392                }
393
394//              Connection                      connection      = null;
395                Connection                      defConn         = null;                 // 5.6.7.0 (2013/07/27) DBID=DEFAULT  のコネクション
396                Connection                      rscConn         = null;                 // 5.6.7.0 (2013/07/27) DBID=RESOURCE のコネクション
397                PreparedStatement       pstmt           = null;
398                ResultSet                       resultSet       = null;
399                boolean                         errFlag         = true;
400                try {
401                        // 4.0.0.0(2007/10/25)ConnectionをConnectionFactory経由で取得するように変更する。
402                        // コンテキスト名で接続しにいく。ApplicationInfoは使わないのでnull
403                        ConnectionFactory.init( CONTEXT_NAME, null ); // ConnectionFactoryの初期化
404//                      connection = ConnectionFactory.connection( null, null );
405//                      connection = ConnectionFactory.connection( RESOURCE_DBID, null );       // 5.5.4.5 (2012/07/27) 初期起動時のDB接続先は、RESOURCE_DBID とする。
406//                      connection.setAutoCommit( false );              // 5.1.2.0 (2010/01/01)
407
408                        defConn = ConnectionFactory.connection( null, null );                   // 5.6.7.0 (2013/07/27) DBID=DEFAULT のコネクション
409                        rscConn = ConnectionFactory.connection( RESOURCE_DBID, null );  // 5.6.7.0 (2013/07/27) DBID=RESOURCE のコネクション
410
411                        // 4.3.6.6 (2009/05/15)
412                        // 5.1.9.0 (2010/08/01) 自動インストールの設定見直し(画面からのインストール対応)
413//                      SystemInstaller installer = new SystemInstaller( connection, new PrintWriter( System.out, true ) );
414                        SystemInstaller installer = new SystemInstaller( defConn , rscConn , new PrintWriter( System.out, true ) );
415                        // 5.10.17.2 (2019/11/22) MODIFY ディレクトリ名を渡すように変更
416//                      installer.autoInsUpd( SYSTEM_ID, CONTEXT_NAME, HOST_URL );
417                        installer.autoInsUpd( SYSTEM_ID, CONTEXT_DIRNM, HOST_URL );
418
419                        // resource パス内のXMLファイルがあれば、先にDB登録します。(DBID=RESOURCE)
420//                      InitFileLoader loader = new InitFileLoader( connection );
421                        InitFileLoader loader = new InitFileLoader( rscConn );          // このコンストラクタは/resource フォルダを検索します。
422                        loader.loadInitFiles( true ) ;
423
424                        // 5.6.6.1 (2013/07/12) xml パス内のXMLファイルがあれば、DB登録します。
425//                      loader = new InitFileLoader( connection, "xml" );
426                        loader = new InitFileLoader( defConn, "xml" );
427                        loader.loadInitFiles( true ) ;
428
429                        // コンテキスト単位のシステムパラメータを GE12 に設定します。
430                        // dbXMLResourceInsert の後に登録する必要があります。
431//                      dbResourceUpdate( connection,sysParam );
432//                      connection.commit();
433                        dbResourceUpdate( rscConn,sysParam );                   // 5.6.7.0 (2013/07/27) DBID=RESOURCE のコネクション
434                        rscConn.commit();
435
436                        // DBを検索して、ユーザー設定リソース情報を取得します。
437//                      pstmt = connection.prepareStatement( QUERY );
438                        pstmt = rscConn.prepareStatement( QUERY );              // 5.6.7.0 (2013/07/27) DBID=RESOURCE のコネクション
439                        pstmt.setString( 1,SYSTEM_ID );
440                        pstmt.setString( 2,HOST_URL ); // 4.1.0.0 (2007/12/21)
441                        Map<String,String> userMap = new HashMap<String,String>(100);
442                        resultSet = pstmt.executeQuery();
443
444                        while( resultSet.next() ) {
445                                String key   = resultSet.getString(1);
446                                String val   = resultSet.getString(2);
447                                if( val != null && val.length() == 0 ) { val = null; }
448                                userMap.put( key,val );
449                        }
450
451                        System.out.println( "    Load DB Resource [" + userMap.size() + "] finished." );
452                        // リソースをマージします。
453                        sysParam.putAll( userMap );
454                        errFlag = false;        // エラーでない
455                }
456                catch (SQLException ex) {
457//                      Closer.rollback( connection );
458                        Closer.rollback( defConn );                     // 5.6.7.0 (2013/07/27) DBID=DEFAULT のコネクション
459                        Closer.rollback( rscConn );                     // 5.6.7.0 (2013/07/27) DBID=RESOURCE のコネクション
460                        LogWriter.log( ex );
461                        String errMsg = ex.getMessage() + ":" + ex.getSQLState() ;
462                        errMsgList.add( errMsg );
463                }
464                catch (UnsupportedEncodingException ex) {
465//                      Closer.rollback( connection );
466                        Closer.rollback( defConn );                     // 5.6.7.0 (2013/07/27) DBID=DEFAULT のコネクション
467                        Closer.rollback( rscConn );                     // 5.6.7.0 (2013/07/27) DBID=RESOURCE のコネクション
468                        LogWriter.log( ex );
469                        String errMsg = "UTF-8 がサポートされていない Java VM は、正規VMではありません。"
470                                                        + ex.getMessage();
471                        errMsgList.add( errMsg );
472                }
473                catch (RuntimeException ex) {
474//                      Closer.rollback( connection );
475                        Closer.rollback( defConn );                     // 5.6.7.0 (2013/07/27) DBID=DEFAULT のコネクション
476                        Closer.rollback( rscConn );                     // 5.6.7.0 (2013/07/27) DBID=RESOURCE のコネクション
477                        // 5.7.2.0 (2014/01/10) RuntimeException は、catch しないようにします。
478//                      LogWriter.log( ex );
479//                      String errMsg = "処理を実行できませんでした。" + HybsSystem.CR
480//                                              + " SYSTEM_ID = [" + SYSTEM_ID + "]" + HybsSystem.CR
481//                                              + ex.getMessage() ;
482//                      errMsgList.add( errMsg );
483                        throw ex ;
484                }
485                finally {
486                        Closer.resultClose( resultSet );
487                        Closer.stmtClose( pstmt );
488                        if( errFlag ) {
489//                              ConnectionFactory.remove( connection, null );
490                                ConnectionFactory.remove( defConn, null );                              // 5.6.7.0 (2013/07/27) DBID=DEFAULT のコネクション
491//                              ConnectionFactory.remove( rscConn, null );                              // 5.6.7.0 (2013/07/27) DBID=RESOURCE のコネクション
492                                ConnectionFactory.remove( rscConn, RESOURCE_DBID );             // 5.6.7.3 (2013/08/23) DBID=RESOURCE 漏れ
493                        }
494                        else {
495//                              ConnectionFactory.close( connection, null );
496                                ConnectionFactory.close( defConn, null );                               // 5.6.7.0 (2013/07/27) DBID=DEFAULT のコネクション
497//                              ConnectionFactory.close( rscConn, null );                               // 5.6.7.0 (2013/07/27) DBID=RESOURCE のコネクション
498                                ConnectionFactory.close( rscConn, RESOURCE_DBID );              // 5.6.7.3 (2013/08/23) DBID=RESOURCE 漏れ
499                        }
500                }
501
502                return sysParam ;
503        }
504
505        /**
506         * エンジン内部定義の初期リソース情報をDB(GE12)に登録します。
507         *
508         * 初期リソース情報は、KBSAKU='0' で登録されている情報で、一旦すべて削除
509         * してから、全てのリソース情報を追加するという形をとります。
510         * ただし、属性情報(名称や概要など)を別途登録する場合は、全てを
511         * 削除せずに、UPDATE する方向で検討したいと思います。
512         * なお、この情報をDB登録する理由は、リソースの設定値を変えたい場合に、
513         * キーが判らない(JavaDOCからしか読み取れない)のでは不便な為に
514         * 用意しておくだけで、内部では SystemData オブジェクトとして定義
515         * されている値を使用するため、このデータベース値は、使用していません。
516         *
517         * @param       conn    登録用コネクション(リソース用)
518         * @param       map             入力システムパラメータマップ
519         * @throws      SQLException データベースアクセスエラー
520         */
521        private static void dbResourceUpdate( final Connection conn,final Map<String,String> map )
522                                throws SQLException {
523
524                String systemId = map.get( "SYSTEM_ID" );
525                String HOST_URL = map.get( "HOST_URL" ); // 4.1.0.0 (2007/12/21)
526
527                // 既存の設定値を全件DELETEします。
528                int delCnt;
529                PreparedStatement pstmt = null;
530                try {
531                        pstmt = conn.prepareStatement( DEL_SYS );
532                        pstmt.setString( 1, systemId );
533                        pstmt.setString( 2, HOST_URL ); // 4.1.0.0 (2007/12/21)
534                        delCnt = pstmt.executeUpdate();
535                }
536                finally {
537                        Closer.stmtClose( pstmt );
538                }
539
540                // 新設定値を全件INSERTします。
541                Set<String> keyset = map.keySet();
542                String[] keys = keyset.toArray( new String[keyset.size()] );
543
544                int insCnt = 0;
545                try {
546                        pstmt = conn.prepareStatement( INS_SYS );
547                        for( int i=0; i<keys.length; i++ ) {
548                                pstmt.setString( 1,systemId );
549                                pstmt.setString( 2,HOST_URL);
550                                pstmt.setString( 3,keys[i] );
551                                pstmt.setInt( 4,( i + 1 ) * 10 );
552                                pstmt.setString( 5,map.get( keys[i] ) );
553                                pstmt.setString( 6,keys[i] );
554                                insCnt += pstmt.executeUpdate();
555                        }
556                }
557                finally {
558                        Closer.stmtClose( pstmt );
559                }
560
561                System.out.print( "    DB Context Resource Reconfiguration " );
562                System.out.println( "DELETE=[" + delCnt + "],INSERT=[" + insCnt + "] finished." );
563        }
564
565        /**
566         *  サーブレットコンテキストのディレクトリ名を取得します。
567         *
568         * @og.rev 5.10.17.2 (2019/11/22) 新規追加
569         *
570         * @param context Servletコンテキスト
571         * @return コンテキストのディレクトリ名
572         */
573        private static String getContextDirNm( final ServletContext context ) {
574                String name = null;
575                try {
576                        String path = context.getResource( "/" ).getFile();
577                        int idx = path.lastIndexOf( '/',path.length()-2 );
578                        name = path.substring( idx+1,path.length()-1 );
579                }
580                catch( MalformedURLException ex ) {
581                        String errMsg = "このパス名は、正しいフォームではありません。 "
582                                                + ex.getMessage();
583                        LogWriter.log( ex );
584                        errMsgList.add( errMsg );
585                }
586                return name ;
587        }
588
589        /**
590         *  ServletContext の名称を取得します。
591         *
592         * コンテキストのアクセスされたパス( /training など )の名称を、
593         * 取得します。(アクセス先の仮想フォルダ名)
594         * 以前は、配備記述子(WEB-INF/web.xml)の display-name 要素を見て、
595         * 無ければ、実フォルダ名を返していました。
596         *
597         * @param  context Servletコンテキスト
598         *
599         * @return コンテキストのコンテキスト名
600         */
601        private static String getContextName( final ServletContext context ) {
602// 5.10.17.2 (2019/11/22) MOIDFY
603//              String name = null;
604//              try {
605//                      String path = context.getResource( "/" ).getFile();
606//                      int idx = path.lastIndexOf( '/',path.length()-2 );
607//                      name = path.substring( idx+1,path.length()-1 );
608//              }
609//              catch( MalformedURLException ex ) {
610//                      LogWriter.log( ex );
611//                      String errMsg = "このパス名は、正しいフォームではありません。 "
612//                                              + ex.getMessage();
613//                      errMsgList.add( errMsg );
614//              }
615//              return name ;
616
617                // 5.10.17.2 (2019/11/22) ServletContext.getContextPath()からコンテキスト名を取得します。
618                // ServletContextから、コンテキスト名の取得
619                String path  = context.getContextPath();
620
621                if(path == null || path.length() == 0) {
622                        // コンテキスト名が取得できない場合(通常は発生しません)
623                        String errMsg = "コンテキスト名が取得出来ませんでした。";
624                        errMsg += "path=[" + path + "]";
625                        LogWriter.log( errMsg );
626                        errMsgList.add(errMsg);
627                }
628
629                // 先頭の「/」は除外
630                return path.substring(1);
631        }
632
633        /**
634         * 指定のクラスの public static なフィールドキーと値のマップを作成します。
635         * 主に、エンジン関連のクラスにパラメータファイルをクラスとして定義し、
636         * エンジンとともに配布します。配布されたクラスを元に、パラメータを
637         * 読み取ります。
638         * この処理は リフレクションを使用してクラスの public static フィールドを
639         * 取得し、LinkedHashMap により、取得順をキープしたまま、Mapを返します。
640         *
641         * @og.rev 5.7.2.0 (2014/01/10) errMsgList は、一旦文字列に変換してから追加します。
642         *
643         * @param  cls クラスオブジェクト
644         *
645         * @return      システムパラメータのマップ
646         */
647        private static Map<String,String> loadParameter( final Class<?> cls ) {     // 4.3.3.6 (2008/11/15) Generics警告対応
648                Field[] field = cls.getFields();        // public フィールドのみ
649                Map<String,String> map = new LinkedHashMap<String,String>( (int)(field.length * 1.5) ); // 負荷係数より大きい目に取る。
650
651                try {
652                        for( int i=0; i<field.length; i++ ) {
653                                if( Modifier.isStatic( field[i].getModifiers() ) ) {
654                                        map.put( field[i].getName() , (String)field[i].get( null ) );
655                                }
656                        }
657                }
658                catch( IllegalAccessException ex ) {
659                        LogWriter.log( ex );
660                        // 5.7.2.0 (2014/01/10) errMsgList は、一旦文字列に変換してから追加します。
661//                      errMsgList.add( ex.getMessage() );
662                        String errMsg = "クラスから、パラメータを取得できませんでした。"       + HybsSystem.CR
663                                                + "  クラス名=[" + cls.getName() + "]"                                      + HybsSystem.CR
664                                                + ex.getMessage();
665                        errMsgList.add( errMsg );
666                }
667
668                System.out.println( "    ClassLoad " + cls.getName() + " Parameter [" + map.size() + "] finished." );
669                return map;
670        }
671
672        /**
673         * 指定のキーワードのファイルをクラスパスより取得し、キーと値のマップを作成します。
674         * 主に、エンジン関連のクラスにパラメータファイルをPlugInクラスとして定義し、配布します。
675         * この処理の取得に、クラスパスの順序が関係します。最初に取得されたキーは、あとから
676         * 読み取られたクラスパスは、再セットしません。
677         *
678         * @og.rev 5.3.6.0 (2011/06/01) 並び順を、キーの名称順とする。
679         * @og.rev 5.7.2.0 (2014/01/10) errMsgList は、一旦文字列に変換してから追加します。
680         * @og.rev 5.7.2.0 (2014/01/10) RuntimeException は、catch しないようにします。
681         *
682         * @param       keyword クラスオブジェクトを検索する元
683         *
684         * @return      キーと値のマップ
685         */
686        private static Map<String,String> loadParameter( final String keyword ) {
687//              Map<String,String> map = new HashMap<String,String>();
688                Map<String,String> map = new TreeMap<String,String>();              // 5.3.6.0 (2011/06/01) 並び順を、キーの名称順とする。
689                try {
690                        ClassLoader loader = Thread.currentThread().getContextClassLoader();
691                        Enumeration<URL> enume = loader.getResources( keyword );          // 4.3.3.6 (2008/11/15) Generics警告対応
692                        while( enume != null && enume.hasMoreElements() ) {
693                                URL url = enume.nextElement();          // 4.3.3.6 (2008/11/15) Generics警告対応
694                                // jar:file:/実ディレクトリ または、file:/実ディレクトリ
695                                String dir = url.getFile();
696        //                      System.out.println( dir );
697
698                                FindClassFiles filenames = new FindClassFiles( dir,keyword );
699                                String[] names = filenames.getFilenames();
700                                for( int i=0; i<names.length; i++ ) {
701                                        String val = names[i];
702                                        String key = val.substring( val.lastIndexOf( '.' )+1 );
703                                        if( key.indexOf( '_' ) >= 0 && !map.containsKey( key ) && key.indexOf( '$' ) < 0 ) {
704                                                map.put( key , val );
705                                        }
706                                }
707                                System.out.println( "    FileCheck " + dir + " [" + names.length + "] find." );
708                        }
709                }
710                catch( IOException ex ) {
711                        LogWriter.log( ex );
712                        // 5.7.2.0 (2014/01/10) errMsgList は、一旦文字列に変換してから追加します。
713//                      errMsgList.add( ex.getMessage() );
714                        String errMsg = "キーワードから、パラメータを取得できませんでした。"     + HybsSystem.CR
715                                                + "  キーワード名=[" + keyword + "]"                                          + HybsSystem.CR
716                                                + ex.getMessage();
717                        errMsgList.add( errMsg );
718                }
719                // 5.7.2.0 (2014/01/10) RuntimeException は、catch しないようにします。
720//              catch( RuntimeException ex ) {
721//                      LogWriter.log( ex );
722//                      errMsgList.add( ex.getMessage() );
723//              }
724                System.out.println( "    FileLoad " + keyword + " Parameter [" + map.size() + "] finished." );
725                return map;
726        }
727}