    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.BufferedReader;
    019import java.io.File;
    020// import java.io.FileFilter;                                                           // 7.0.1.4 (2018/11/26)
    021import java.io.InputStream;
    022import java.io.InputStreamReader;
    023import java.io.PrintWriter;
    024import java.io.Reader;
    025import java.io.UnsupportedEncodingException;
    026import java.sql.Connection;
    027import java.sql.PreparedStatement;
    028import java.sql.ResultSet;
    029import java.sql.SQLException;
    030import java.sql.Statement;
    031import java.util.ArrayList;
    032import java.util.List;
    033import java.util.Locale;
    034
    035import org.opengion.fukurou.system.BuildNumber;                 // 6.4.2.0 (2016/01/29) hayabusa.common.BuildNumber → fukurou.system.BuildNumber に移動
    036import org.opengion.fukurou.system.Closer;
    037import org.opengion.fukurou.system.HybsConst;                   // 7.2.3.1 (2020/04/17)
    038import org.opengion.fukurou.util.FileUtil;
    039import org.opengion.fukurou.util.StringUtil;
    040import org.opengion.fukurou.util.ZipArchive;                    // 6.0.0.0 (2014/04/11) ZIP API変更
    041import org.opengion.fukurou.xml.HybsXMLSave;
    042import org.opengion.fukurou.db.DBUtil;
    043
    044/**
    045 * システムの自動インストールと自動更新を行います。
    046 *
    047 * (1)初期インストール・自動更新(#autoInsUpd)
    048 *   ①初期自動インストールを行うには、起動時の環境変数にINSTALL_CONTEXTSが
    049 *     設定されている必要があります。
    050 *     この環境変数が設定されている場合、システムリソーステーブル(GE12)が存在しなければ、
    051 *     エンジンがインストールされていないと判断し、自動インストールを行います。
    052 *     INSTALL_CONTEXTSにge,gfが指定されている場合は、開発環境を含めたフルバージョンが
    053 *     インストールされます。
    054 *     geのみが指定されている場合は、コアモジュールであるgeのみがインストールされます。
    055 *
    056 *     インストールスクリプトは、
    057 *      webapps/[CONTEXT]/db/[DBNAME]/xml/install                       DBID=DEFAULT
    058 *      webapps/[CONTEXT]/db/[DBNAME]/xml/update                        DBID=DEFAULT
    059 *     以下にあるXMLファイルが全て実行されます。
    060 *     また、同時に
    061 *      webapps/[CONTEXT]/db/common/xml/install                         DBID=DEFAULT
    062 *      webapps/[CONTEXT]/db/common/xml/update                          DBID=DEFAULT
    063 *      webapps/[CONTEXT]/db/resource/xml/install                       DBID=RESOURCE   (5.6.7.0 (2013/07/27) 追加)
    064 *      webapps/[CONTEXT]/db/resource/xml/update                        DBID=RESOURCE   (5.6.7.0 (2013/07/27) 追加)
    065 *     以下にあるデータロードスクリプトも全て実行されます。
    066 *
    067 *   ②自動更新については、システムリソーステーブル(GE12)の更新と、各システムの更新の2つがあります。
    068 *     GE12更新の判断基準は、システムID='**'に格納されているバージョン(同一のGE12を使用し
    069 *     ているシステムの最大バージョン番号)がアップした場合です。
    070 *     この場合に、エンジン内部で保持しているXMLファイルよりシステムリソースの再ロードを行います。
    071 *     各システムの更新の判断基準は、システムID=各システムのバージョン番号がアップされた場合です。
    072 *
    073 *     更新スクリプトは、
    074 *      webapps/[CONTEXT]/db/[DBNAME]/xml/update                        DBID=DEFAULT
    075 *     以下にあるXMLファイルが全て実行されます。
    076 *     また、同時に
    077 *      webapps/[CONTEXT]/db/common/xml/update                          DBID=DEFAULT
    078 *      webapps/[CONTEXT]/db/resource/xml/update                        DBID=RESOURCE   (5.6.7.0 (2013/07/27) 追加)
    079 *     以下にあるデータロードスクリプトも全て実行されます。
    080 *
    081 * (2)インストール(#install)
    082 *  自動インストールは、通常は画面からコンテキストのアーカイブを指定して行います。
    083 *
    084 *  アーカイブの内容としては、アーカイブの直下がコンテキスト名のフォルダとなっている必要があります。
    085 *  このコンテキストフォルダをwebapps以下に展開します。
    086 *
    087 *  また、Tomcatのコンテキストの設定ファイル、([CONTEXT].xml)が"WEB-INFの直下を配置している必要があります。
    088 *
    089 *  このインストールでは、Tomcatに対するコンテキスト定義のXMLファイルの配備及び、
    090 *  各種DB、データのロードを行います。
    091 *
    092 *  インストールスクリプトは、
    093 *   webapps/[CONTEXT]/db/[DBNAME]/xml/install                          DBID=DEFAULT
    094 *  以下にあるXMLファイルが全て実行されます。
    095 *  また、同時に
    096 *   webapps/[CONTEXT]/db/common/xml/install                            DBID=DEFAULT
    097 *   webapps/[CONTEXT]/db/resource/xml/install                          DBID=RESOURCE   (5.6.7.0 (2013/07/27) 追加)
    098 *  以下にあるデータロードスクリプトも全て実行されます。
    099 *
    100 * @og.rev 4.3.6.6 (2009/05/15) 新規作成
    101 * @og.rev 7.0.2.3 (2019/04/01) xmlﾌｧｲﾙのﾀｲﾑｽﾀﾝﾌﾟによる更新制御を入れます。(保留)
    102 * @og.group 初期化
    103 *
    104 * @version  4.0
    105 * @author   Hiroki Nakamura
    106 * @since    JDK5.0,
    107 */
    108public final class SystemInstaller {
    109        private final Connection defConn;               // 5.6.7.0 (2013/07/27) DBID=DEFAULT  のコネクション
    110        private final Connection rscConn;               // 5.6.7.0 (2013/07/27) DBID=RESOURCE のコネクション
    111        private final PrintWriter out;                  // 5.1.9.0 (2010/08/01)
    112        private final String DBNAME;                    // 5.5.4.4 (2012/07/20) 共通化 (DBID=DEFAULT のDB名)
    113
    114        /** エンジン共通パラメータ(SYSTEM_ID='**' KBSAKU='0')のXML ファイルの指定  {@value}        */
    115        public static final String GE12_XML = "org/opengion/hayabusa/common/GE12.xml";
    116
    117        /** エンジン共通パラメータ(SYSTEM_ID='**' KBSAKU='0')のENGINE_INFO 読み取りクエリー {@value}        */
    118        public static final String SEL_MAX_ENG = "select PARAM from GE12"
    119                                                                                                + " where SYSTEM_ID='**'"
    120                                                                                                + " and PARAM_ID='ENGINE_INFO' and KBSAKU='0' and FGJ='1'" ;
    121
    122        /** エンジン個別(SYSTEM_ID='個別' KBSAKU='0'  CONTXT_PATH='自身')のバージョン情報を取得するクエリー {@value} 4.3.6.6 (2009/05/15) */
    123        public static final String SEL_SYS_ENG = "select PARAM from GE12"
    124                                                                                                + " where SYSTEM_ID=? and CONTXT_PATH=?"
    125                                                                                                + " and PARAM_ID='ENGINE_INFO' and KBSAKU='0' and FGJ='1'" ;
    126
    127        private static final String FS                  = File.separator ;                                              // 5.5.4.4 (2012/07/20) static化
    128//      private static final String APP_BASE    = System.getenv( "APP_BASE" ) + FS;             // 5.5.4.4 (2012/07/20) static化
    129//      private static final String APP_BASE    = StringUtil.nval(System.getenv( "APP_BASE" ),System.getProperty( "APP_BASE" )) + FS; // 5.9.30.2 (2018/03/23)
    130        private static final String APP_BASE    = HybsConst.getenv( "APP_BASE" ) + FS; // 7.2.3.1 (2020/04/17)
    131
    132//      // 7.0.1.4 (2018/11/26) FileFilter を利用して、フォルダの絞り込みを行う。
    133//      private static final FileFilter INS_FLTR = file -> {
    134//                                                                                                      if( file.isFile() ) { return true; }
    135//                                                                                                      final String name = file.getName().toUpperCase( Locale.JAPAN );
    136//                                                                                                      return file.isDirectory() && ( name.contains( "INSTALL" ) ||  name.contains( "UPDATE" ) );
    137//                                                                                              };
    138//
    139//      private static final FileFilter UPD_FLTR = file -> {
    140//                                                                                                      if( file.isFile() ) { return true; }
    141//                                                                                                      final String name = file.getName().toUpperCase( Locale.JAPAN );
    142//                                                                                                      return file.isDirectory() && name.contains( "UPDATE" );
    143//                                                                                              };
    144
    145        /**
    146         * データベース処理をおこなうに当たり、処理のタイプを指定するための、enum 定義です。
    147         * 文字列で扱っていた箇所を、enum と置き換えます。
    148         *
    149         * @og.rev 5.5.4.4 (2012/07/20) 新規追加
    150         */
    151        private enum EXEC_TYPE { INSTALL , UPDATE } ;
    152//      private static enum EXEC_TYPE { INSTALL , UPDATE } ;
    153
    154//      /**
    155//       * データベース処理をおこなうに当たり、処理のタイプを指定するための、enum 定義です。
    156//       * 文字列で扱っていた箇所を、enum と置き換えます。
    157//       *
    158//       * @og.rev 5.5.4.4 (2012/07/20) 新規追加
    159//       * @og.rev 7.0.1.4 (2018/11/26) FileFilter を利用して、フォルダの絞り込みを行う。
    160//       */
    161//      private static enum EXEC_TYPE {
    162//              INSTALL( INS_FLTR ) ,
    163//              UPDATE(  UPD_FLTR ) ;
    164//
    165//              private final FileFilter filter ;
    166//
    167//              /** コンストラクター
    168//               *
    169//               * @param filter ファイルの絞込みに使用するフィルター
    170//               */
    171//              private EXEC_TYPE( final FileFilter filter ) { this.filter = filter; }
    172//
    173//              /** ファイルの絞込みに使用するフィルターを返します。
    174//               *
    175//               * @return ファイルの絞込みに使用するフィルター
    176//               */
    177//              public FileFilter getFilter() { return filter; }
    178//      } ;
    179
    180        /**
    181         * システムインストール・更新クラスのコンストラクタです
    182         *
    183         * なお、このクラスの中の処理で、エラーが発生しても、Connection は、close 等しません。
    184         * 呼び出し元で、try ～ finally で、処理してください。
    185         *
    186         * @og.rev 5.5.4.4 (2012/07/20) VERSIONは、直接 BuildNumber.ENGINE_INFO を使用。
    187         * @og.rev 5.6.7.0 (2013/07/27) アプリケーション登録用とリソース登録用のコネクションを分ける
    188         * @og.rev 5.9.24.1 (2017/09/08) DB名を出力する
    189         *
    190         * @param       defConn アプリケーション登録用コネクション
    191         * @param       rscConn リソース登録用コネクション
    192         * @param       out     表示用のWriter
    193         */
    194        public SystemInstaller( final Connection defConn, final Connection rscConn, final PrintWriter out ) {
    195                this.defConn = defConn;                 // 5.6.7.0 (2013/07/27) アプリケーション登録用
    196                this.rscConn = rscConn;                 // 5.6.7.0 (2013/07/27) リソース登録用
    197                this.out = out;
    198
    199                // 5.6.7.0 (2013/07/27) ProductName は、DBUtil 経由で取得する。
    200                DBNAME = DBUtil.getProductName( defConn );                                              // 5.6.7.0 (2013/07/27) DBID=DEFAULT  のDB名
    201                out.println( "    Database Information ( " + DBNAME + " )" );   // 5.9.24.1
    202        }
    203
    204        /**
    205         * システムの初期自動インストール・自動更新を行います。
    206         *
    207         * 詳細は、クラスドキュメントを参照して下さい。
    208         *
    209         * @og.rev 5.1.9.0 (2010/08/01) 新規作成
    210         * @og.rev 5.5.4.4 (2012/07/20) VERSIONは、直接 BuildNumber.ENGINE_INFO を使用。
    211         * @og.rev 7.0.1.4 (2018/11/26) 初期自動インストール(oldMaxVersion == "none")時でも、loadXMLScript(Update)とdbXMLResourceInsert は行う
    212         *
    213         * @param systemId システムID
    214         * @param context コンテキスト名
    215         * @param hostUrl ホスト文字列
    216         * @throws UnsupportedEncodingException エンコード名 "UTF-8" が存在しなかった場合。
    217         * @see   #dbXMLResourceInsert()
    218         */
    219        public void autoInsUpd( final String systemId, final String context, final String hostUrl ) throws UnsupportedEncodingException  {
    220                final String oldMaxVersion    = getOldMaxVersion();
    221                final String oldSystemVersion = getOldSystemVersion( systemId, hostUrl );
    222
    223                out.println( "    System Version Information ( " + systemId + " )" );
    224                out.println( "      Load Version [ " + BuildNumber.ENGINE_INFO + " ]" );                // 5.5.4.4 (2012/07/20)
    225                out.println( "        -> Resource Version[ " + oldMaxVersion + " ]" );
    226                out.println( "        -> System   Version[ " + oldSystemVersion + " ] " );
    227
    228                // 初期自動インストール
    229                if( "none".equalsIgnoreCase( oldMaxVersion ) ) {
    230                        out.println( "      !!! openGion ENVIROMENT IS NOT INSTALLED !!!" );
    231
    232//                      final String INSTALL_CONTEXTS = System.getenv( "INSTALL_CONTEXTS" );
    233                        final String INSTALL_CONTEXTS = HybsConst.getenv( "INSTALL_CONTEXTS" );         // 7.2.3.1 (2020/04/17)
    234                        if( INSTALL_CONTEXTS == null || INSTALL_CONTEXTS.isEmpty() ) {
    235                                out.println( "        !!! \"INSTALL_CONTEXT\" IS NOT CONFIGURED\" !!!" );
    236                                out.println( "        !!! \"SET ENRIVOMENT PARAMETER NAMED \"INSTALL_CONTEXT\" ON INIT_SCRIPT !!!" );
    237//                              return;
    238
    239                                // 7.0.1.4 (2018/11/26) 初期自動インストール(oldMaxVersion == "none")時でも、loadXMLScript(Update)とdbXMLResourceInsert は行う
    240                                out.println( "      Start Enviroment Update ( " + context + " )" );
    241                                loadXMLScript( EXEC_TYPE.UPDATE , context );
    242                                out.println( "      Completed               ( " + context + " )" );
    243                        }
    244                        else {
    245                                out.println( "      Start Initiall Enviroment Install : install type ( " + INSTALL_CONTEXTS + " )" );
    246                                final String[] insSys = StringUtil.csv2Array( INSTALL_CONTEXTS );
    247                                for( int i=0; i<insSys.length; i++ ) {
    248                                        out.println( "        Install    ( " + insSys[i] + " )" );
    249                                        loadXMLScript( EXEC_TYPE.INSTALL, insSys[i] );
    250                                        out.println( "        Completed  ( " + insSys[i] + " )" );
    251                                }
    252                        }
    253
    254                        out.println( "      Start SystemParameter Reload" );
    255                        dbXMLResourceInsert();
    256                        out.println( "      Completed" );
    257                }
    258                // 自動更新
    259                else {
    260                        if( oldSystemVersion == null || oldSystemVersion.compareTo( BuildNumber.ENGINE_INFO ) < 0 ){            // 5.5.4.4 (2012/07/20)
    261                                out.println( "      Start Enviroment Update ( " + context + " )" );
    262                                loadXMLScript( EXEC_TYPE.UPDATE , context );
    263                                out.println( "      Completed               ( " + context + " )" );
    264                        }
    265
    266                        if( oldMaxVersion == null || oldMaxVersion.compareTo( BuildNumber.ENGINE_INFO ) < 0 ){                          // 5.5.4.4 (2012/07/20)
    267                                out.println( "      Start SystemParameter Reload" );
    268                                dbXMLResourceInsert();
    269                                out.println( "      Completed" );
    270                        }
    271                }
    272        }
    273
    274        /**
    275         * システムの自動インストールを行います。
    276         *
    277         * 詳細は、クラスドキュメントを参照して下さい。
    278         *
    279         * @og.rev 5.1.9.0 (2010/08/01) 新規作成
    280         * @og.rev 5.5.4.4 (2012/07/20) FS , APP_BASE を、共通に設定
    281         * @og.rev 6.0.0.0 (2014/04/11) ZIP API変更
    282         * @og.rev 7.2.3.1 (2020/04/17) System.getenv → HybsConst.getenv 変更(サービス化対応)
    283         *
    284         * @param buildArchive コンテキストのアーカイブファイル
    285         */
    286        public void install( final File buildArchive ) {
    287
    288                out.println( "      Check Archive File and Enviroment" );
    289
    290                // アーカイブの存在チェック
    291                if( !buildArchive.exists() ) {
    292                        out.println( "        !!! Archive File does not exists File=[ " + buildArchive.getAbsolutePath() + "] !!!" );
    293                        out.println( "        !!! Install Aborted !!! " );
    294                        return;
    295                }
    296
    297                // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid declaring a variable if it is unreferenced before a possible exit point.
    298                final String tempDir    = HybsSystem.sys( "REAL_PATH" ) + HybsSystem.sys( "FILE_URL" ) + System.currentTimeMillis() + FS;
    299//              final String ctxtXmlDir = System.getenv( "CATALINA_HOME" ) + FS + "conf" + FS + System.getenv( "ENGINE_NAME" ) + FS + "localhost" + FS;
    300                final String ctxtXmlDir = HybsConst.getenv( "CATALINA_HOME" ) + FS + "conf" + FS + HybsConst.getenv( "ENGINE_NAME" ) + FS + "localhost" + FS;   // 7.2.3.1 (2020/04/17)
    301
    302                // アーカイブを一時ファイルに展開します。
    303                ZipArchive.unCompress( new File( tempDir ), buildArchive );                             // 6.0.0.0 (2014/04/11) ZIP API変更
    304
    305                // アーカイブの内容チェック
    306                final File[] ctxts = new File( tempDir ).listFiles();
    307                // 6.3.9.0 (2015/11/06) null になっている可能性がある(findbugs)
    308                if( ctxts != null ) {
    309                        for( final File ctxt : ctxts ) {
    310                                // 5.1.9.0 (2010/08/01) if の条件を入れ替えます。(Avoid if(x != y) ..; else ..;)
    311                                final String context = ctxt.getName();
    312                                if( ctxt.isDirectory() ) {
    313                                        // アーカイブ中に[CONTEXT].xmlが存在していない場合はエラー(何も処理しない)
    314                                        final File srcCtxtXml = new File( tempDir + context + FS + "WEB-INF" + FS + context + ".xml" );
    315                                        if( !srcCtxtXml.exists() ) {
    316                                                out.println( "        !!! Context XML Does not exists =[ " + srcCtxtXml.getAbsolutePath() + "] !!!" );
    317                                                out.println( "        !!! Install Aborted !!! " );
    318                                                return;
    319                                        }
    320
    321                                        // [CONTEXT].xmlが既に存在している場合はエラー(何も処理しない)
    322                                        final File ctxtXml = new File( ctxtXmlDir + context + ".xml" );
    323                                        if( ctxtXml.exists() ) {
    324                                                out.println( "        !!! Context XML File Already Installed File=[ " + ctxtXml.getAbsolutePath() + "] !!!" );
    325                                                out.println( "        !!! Install Aborted !!! " );
    326                                                return;
    327                                        }
    328
    329                                        // webapps/[CONTEXT]が既に存在している場合はエラー(何も処理しない)
    330                                        final File webAppsDir = new File( APP_BASE + context );
    331                                        if( webAppsDir.exists() ) {
    332                                                out.println( "        !!! Context Path Already Exists Path=[ " + webAppsDir.getAbsolutePath() + "] !!!" );
    333                                                out.println( "        !!! Install Aborted !!! " );
    334                                                return;
    335                                        }
    336
    337                                        out.println( "        This Archive includes SYSTEM ( " + context + " ) for Install" );                  // 5.5.4.4 (2012/07/20)
    338                                }
    339                                // ファイルが含まれている場合はエラー(何も処理しない)
    340                                else {
    341                                        out.println( "        !!! This Archive is not Installer. Because include FILE not DIRECTORY. File=[ " + context + "] !!!" );    // 5.5.4.4 (2012/07/20)
    342                                        out.println( "        !!! Install Aborted !!! " );
    343                                        return;
    344                                }
    345                        }
    346
    347                        // アーカイブをコンテキストファイル以下にコピー
    348                        for( final File ctxt : ctxts ) {
    349                                final String context = ctxt.getName();
    350                                out.println( "      Start Enviroment Install ( " + context + " )" );
    351
    352                                // コンテキストのファイルをコピーします。
    353                                FileUtil.copyDirectry( tempDir + context, APP_BASE + context );
    354
    355                                // [CONTEXT].xmlをTomcatのconf以下に展開します。
    356                                FileUtil.copy( tempDir + context + FS + "WEB-INF" + FS + context + ".xml", ctxtXmlDir + context + ".xml" );
    357
    358                                // DBスクリプトをロードします。
    359                                loadXMLScript( EXEC_TYPE.INSTALL , context );
    360                                out.println( "      Completed                ( " + context + " )" );
    361                        }
    362                }
    363                out.println( "      Install Process All Completed." );
    364        }
    365
    366        /**
    367         * インストール、更新用のXMLスクリプトをロードします。
    368         *
    369         * @og.rev 5.0.0.2 (2009/09/15) .xmlファイル以外は読み込まないように修正
    370         * @og.rev 5.1.1.0 (2009/12/01) コメントを出して、処理中ということが判る様にします。
    371         * @og.rev 5.1.9.0 (2010/08/01) DB非依存の定義・データの読み込み対応
    372         * @og.rev 5.5.4.4 (2012/07/20) FS , APP_BASE , DBNAME を、共通に設定
    373         * @og.rev 5.6.7.0 (2013/07/27) アプリケーション登録用とリソース登録用のコネクションを分ける
    374         * @og.rev 8.4.2.0 (2023/03/03) DBｽｸﾘﾌﾟﾄなしｴﾗｰ時のﾒｯｾｰｼﾞを少し和らげる。
    375         *
    376         * @param       type    更新タイプ[EXEC_TYPE.INSTALL/EXEC_TYPE.UPDATE]
    377         * @param       context コンテキスト名
    378         */
    379        private void loadXMLScript( final EXEC_TYPE type, final String context ) {
    380                // DB名からスクリプトを格納しているフォルダを探します。
    381                final String scriptBase = APP_BASE + context.toLowerCase( Locale.JAPAN ) + FS + "db";
    382                final File[] dbDir = new File( scriptBase ).listFiles();
    383                if( dbDir == null || dbDir.length == 0 ) {
    384                        out.println( "             DB Folder not found. [" + scriptBase + "]"  );
    385                        return;
    386                }
    387
    388                String scriptPath = null;
    389                for( int i=0; i<dbDir.length; i++ ) {
    390                        if( DBNAME.indexOf( dbDir[i].getName() ) >= 0 ) {
    391                                scriptPath = dbDir[i].getAbsolutePath();
    392                                break;
    393                        }
    394                }
    395                if( scriptPath == null ) {
    396//                      out.println( "             !!! Script Folder for [ " + DBNAME + " ] not found !!!" );
    397                        out.println( "             DB Script not found. [" + DBNAME + "]" );    // 8.4.2.0 (2023/03/03)
    398                        return;
    399                }
    400
    401                // webapps/[CONTEXT]/db/[DBNAME]/
    402                execScripts( type , scriptPath , defConn );                                             // 5.6.7.0 (2013/07/27) DBID=DEFAULT に登録
    403
    404                // 5.1.9.0 (2010/08/01) DB非依存の定義・データの読み込み対応
    405                // webapps/[CONTEXT]/db/common/
    406                execScripts( type , scriptBase + FS + "common" , defConn );             // 5.6.7.0 (2013/07/27) DBID=DEFAULT に登録
    407
    408                // 5.6.7.0 (2013/07/27) DBID=RESOURCE に登録
    409                // webapps/[CONTEXT]/db/resource/
    410                execScripts( type , scriptBase + FS + "resource" , rscConn );   // 5.6.7.0 (2013/07/27) DBID=RESOURCE に登録
    411        }
    412
    413        /**
    414         * XMLファイルで定義されたDBスクリプトを実行します。
    415         *
    416         * 引数のtypeに応じて、処理するフォルダが異なります。
    417         *   type=INSTALL の場合は、[scriptPath]/xml/install と、[scriptPath]/xml/update 以下の xml ファイル
    418         *   type=それ以外の場合は、[scriptPath]/xml/update 以下の xml ファイル
    419         * です。
    420         *
    421         * 現時点では、scriptPath には、下記の ３種類のアドレスが渡され、それぞれ、登録するコネクションが異なります。
    422         *   webapps/[CONTEXT]/db/[DBNAME]/                     DBID=DEFAULT
    423         *   webapps/[CONTEXT]/db/common/                       DBID=DEFAULT
    424         *   webapps/[CONTEXT]/db/resource/                     DBID=RESOURCE
    425         *
    426         * @og.rev 5.1.9.0 (2010/08/01) 新規作成
    427         * @og.rev 5.5.4.4 (2012/07/20) FS , APP_BASE を、共通に設定
    428         * @og.rev 5.5.8.4 (2012/11/22) firebird対応。フォルダ単位commitを行う
    429         * @og.rev 5.6.7.0 (2013/07/27) Connection引数追加。リソースとアプリを切り分ける。
    430         * @og.rev 5.6.9.2 (2013/10/18) EXEC_SQL のエラー時に Exception を発行しない。
    431//       * @og.rev 7.0.1.4 (2018/11/26) FileFilter を利用して、フォルダの絞り込みを行う。
    432//       * @og.rev 7.0.2.3 (2019/04/01) xmlﾌｧｲﾙのﾀｲﾑｽﾀﾝﾌﾟによる更新制御を入れます。(保留)
    433         * @og.rev 7.0.6.1 (2019/10/11) xmlﾌｧｲﾙのﾀｲﾑｽﾀﾝﾌﾟによる更新制御を入れます。
    434         *
    435         * @param       type            更新タイプ[EXEC_TYPE.INSTALL/EXEC_TYPE.UPDATE]
    436         * @param       scriptPath      XMLファイルのあるパス
    437         * @param       conn            コネクションオブジェクト
    438         */
    439        private void execScripts( final EXEC_TYPE type, final String scriptPath, final Connection conn ) {
    440                // webapps/[CONTEXT]/db/[DBNAME]/xml/(install|update) 内のスクリプトを実行します
    441                final List<String> list = new ArrayList<>();
    442
    443//              // 7.0.1.4 (2018/11/26) FileFilter を利用して、フォルダの絞り込みを行う。
    444//              //                    対象フォルダのトップ                  フィルター         ｿｰﾄ   結果   isCopy(コピー中ファイルを含む)
    445//              FileUtil.getFileList( new File( scriptPath  + FS + "xml" ), type.getFilter() , true, list , true );
    446
    447                if( type == EXEC_TYPE.INSTALL ) {
    448                        FileUtil.getFileList( new File( scriptPath  + FS + "xml" + FS + "install" ), true, list );
    449                        FileUtil.getFileList( new File( scriptPath  + FS + "xml" + FS + "update"  ), true, list );
    450                }
    451                else {
    452                        FileUtil.getFileList( new File( scriptPath  + FS + "xml" + FS + "update"  ), true, list );
    453
    454                        /*******************************************************************************
    455                         * updateの場合に、更新前のバージョンからの変更スクリプトを実行する機能が必要
    456                         *******************************************************************************/
    457                }
    458
    459                if( ! list.isEmpty() ) {
    460                        String dir1 = null;             // 5.1.1.0 (2009/12/01)
    461                        for( final String name : list ) {
    462                                if( name.endsWith( ".xml" ) ) {         // 5.0.0.2 (2009/09/15)
    463                                        final File xml = new File( name );
    464//                                      // 7.0.2.3 (2019/04/01) xmlﾌｧｲﾙのﾀｲﾑｽﾀﾝﾌﾟによる更新制御を入れます。(保留)
    465                                        // 7.0.6.1 (2019/10/11) xmlﾌｧｲﾙのﾀｲﾑｽﾀﾝﾌﾟによる更新制御を入れます。(復活)
    466                                        if( xml.lastModified() > 0 ) {
    467                                                // 5.1.1.0 (2009/12/01) 処理中コメント：フォルダ単位に表示
    468                                                final String dir2 = xml.getParent();
    469                                                if( dir1 == null || !dir1.equalsIgnoreCase( dir2 ) ) {
    470                                                        out.println( "            processing ... " + dir2 );
    471                                                        dir1 = dir2;
    472                                                        Closer.commit( conn );                  // 5.6.7.0 (2013/07/27) Connection引数追加
    473                                                }
    474
    475                                                final Reader reader = FileUtil.getBufferedReader( xml, "UTF-8" );                       // 6.2.0.0 (2015/02/27) BufferedReader を２重にしていた。
    476                                                final HybsXMLSave save = new HybsXMLSave( conn, xml.getName() );                        // 5.6.7.0 (2013/07/27) Connection引数追加
    477                                                save.onExecErrException( false );       // 5.6.9.2 (2013/10/18) EXEC_SQL のエラー時に Exception を発行しない。
    478                                                save.insertXML( reader );
    479
    480                                                // 7.0.6.1 (2019/10/11) xmlﾌｧｲﾙのﾀｲﾑｽﾀﾝﾌﾟによる更新制御を入れます。(復活)
    481//                                              xml.setLastModified( 0L );                      // 7.0.2.3 (2019/04/01) (保留) → 7.0.6.1 (2019/10/11) (復活)
    482                                                if( !xml.setLastModified( 0L ) ) {      // 7.3.0.0 (2021/01/06) SpotBugs 例外的戻り値を無視しているメソッド
    483                                                        out.println( "            LastModified Set Error! " + name );
    484                                                }
    485                                        }
    486                                }
    487                        }
    488                        Closer.commit( conn );                  // 5.6.7.0 (2013/07/27) メソッド内でコミット処理を行う。
    489                        out.println( "            DB Enviroment " + type + "ed , [ " + list.size() + " ] scripts loaded " );
    490                }
    491        }
    492
    493        /**
    494         * 最後に起動された際のバージョン番号を取得します。(システムID='**')
    495         *
    496         * エンジンがまだインストールされていない等の原因でエラーが発生した場合は、
    497         * "none"という文字列を返します。
    498         *
    499         * @og.rev 5.1.1.0 (2009/12/01) 実行エラー時に、rollback を追加(PostgreSQL対応)
    500         * @og.rev 5.6.7.0 (2013/07/27) リソース用コネクションから取り出します。
    501         * @og.rev 5.7.2.0 (2014/01/10) テーブルが無いのに正常終了するケースがある為、ver の初期値を "none" にしておきます。
    502         * @og.rev 6.4.2.1 (2016/02/05) try-with-resources 文で記述。
    503         *
    504         * @return      バージョン番号
    505         */
    506        private String getOldMaxVersion() {
    507                // エンジンパラメータのエンジン情報(バージョン番号 + ビルドタイプ)を取得します。
    508                String                          ver             = "none";                               // 5.7.2.0 (2014/01/10) 初期値を null ⇒ "none" へ変更。
    509
    510                // 6.4.2.1 (2016/02/05) try-with-resources 文
    511                try( Statement stmt      = rscConn.createStatement();                                   // setFetchSize は行わない。(ﾃﾞｰﾀ件数が少ない)
    512                         ResultSet resultSet = stmt.executeQuery( SEL_MAX_ENG ) ) {
    513                        while( resultSet.next() ) {
    514                                ver = resultSet.getString(1);
    515                        }
    516                }
    517                catch( final SQLException ex ) {                // catch は、close() されてから呼ばれます。
    518                        Closer.rollback( rscConn );                     // 5.6.7.0 (2013/07/27)
    519                }
    520                return ver;
    521        }
    522
    523        /**
    524         * 最後に起動された際のバージョン番号を取得します。(システムID=各システム)
    525         *
    526         * @og.rev 5.1.1.0 (2009/12/01) 実行エラー時に、rollback を追加(PostgreSQL対応)
    527         * @og.rev 5.6.7.0 (2013/07/27) リソース用コネクションから取り出します。
    528         * @og.rev 6.4.2.1 (2016/02/05) try-with-resources 文で記述。
    529         *
    530         * @param       systemId        システムID
    531         * @param       hostUrl         ホストURL
    532         *
    533         * @return      バージョン番号
    534         */
    535        private String getOldSystemVersion( final String systemId, final String hostUrl ) {
    536                // エンジンパラメータのエンジン情報(バージョン番号 + ビルドタイプ)を取得します。
    537                String                          ver             = null;
    538                // 6.4.2.1 (2016/02/05) try-with-resources 文
    539                try( PreparedStatement pstmt = rscConn.prepareStatement( SEL_SYS_ENG ) ) {      // setFetchSize は行わない。(ﾃﾞｰﾀ件数が少ない)
    540                        pstmt.setString( 1, systemId );
    541                        pstmt.setString( 2, hostUrl );
    542                        try( ResultSet resultSet = pstmt.executeQuery() ) {
    543                                while( resultSet.next() ) {
    544                                        ver = resultSet.getString(1);
    545                                }
    546                        }
    547                }
    548                catch( final SQLException ex ) {                                // catch は、close() されてから呼ばれます。
    549                        Closer.rollback( rscConn );                     // 5.6.7.0 (2013/07/27)
    550                }
    551                return ver;
    552        }
    553
    554        /**
    555         * エンジン内部定義の初期リソース情報をDB(GE12)に登録します。
    556         *
    557         * 初期リソース情報は、KBSAKU='0' で登録されている情報で、一旦すべて削除
    558         * してから、全てのリソース情報を追加するという形をとります。
    559         * リソースは、すでに、Oracle XDK により XMLファイル化してあります。
    560         * なお、この情報をDB登録する理由は、リソースの設定値を変えたい場合に、
    561         * キーが判らない(JavaDOCからしか読み取れない)のでは不便な為に
    562         * 用意しておくだけで、内部では SystemData オブジェクトとして定義
    563         * されている値を使用するため、このデータベース値は、使用していません。
    564         *
    565         * @og.rev 4.3.6.6 (2009/05/15) バージョン判定部分を分離
    566         * @og.rev 5.6.7.0 (2013/07/27) リソース用コネクションに登録します。
    567         * @og.rev 5.6.9.2 (2013/10/18) EXEC_SQL のエラー時に Exception を発行しない。
    568         *
    569         * @throws UnsupportedEncodingException エンコード名 "UTF-8" が存在しなかった場合。
    570         */
    571        private void dbXMLResourceInsert() throws UnsupportedEncodingException {
    572                // 新設定値を全件INSERTします。
    573                // common フォルダにセットして、ClassLoader で読み取る方法
    574                final ClassLoader loader = Thread.currentThread().getContextClassLoader();
    575                final InputStream stream = loader.getResourceAsStream( GE12_XML );
    576
    577                final Reader reader = new BufferedReader( new InputStreamReader( stream,"UTF-8" ) );
    578                final HybsXMLSave save = new HybsXMLSave( rscConn,"GE12" );                     // 5.6.7.0 (2013/07/27)
    579                save.onExecErrException( false );               // 5.6.9.2 (2013/10/18) EXEC_SQL のエラー時に Exception を発行しない。
    580                save.insertXML( reader );
    581                final int insCnt = save.getInsertCount();
    582                final int delCnt = save.getDeleteCount();
    583
    584                out.print( "        XML Engine Resource Reconfiguration " );
    585                out.println( "DELETE=[" + delCnt + "],INSERT=[" + insCnt + "] finished." );
    586
    587                // 5.6.7.0 (2013/07/27) コミットをメソッドの中で処理します。
    588                Closer.commit( rscConn );
    589        }
    590}