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