    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.util.Date;
    019import java.util.Map;
    020import java.util.EnumSet;
    021import java.io.IOException;
    022
    023import javax.servlet.ServletContextListener;
    024import javax.servlet.ServletContextEvent;
    025import javax.servlet.ServletContext;
    026import javax.servlet.ServletRegistration;
    027import javax.servlet.FilterRegistration;
    028import javax.servlet.DispatcherType;
    029import javax.servlet.annotation.WebListener;                            // 6.3.4.0 (2015/08/01)
    030
    031import org.apache.catalina.ContainerListener;                           // 6.3.9.0 (2015/11/06)
    032import org.apache.catalina.ContainerEvent;                                      // 6.3.9.0 (2015/11/06)
    033
    034import org.opengion.fukurou.db.ConnectionFactory;
    035import org.opengion.fukurou.util.Cleanable;
    036import org.opengion.fukurou.util.HybsEntry;
    037// import org.opengion.fukurou.util.URLConnect;                                 // 6.9.0.0 (2018/01/31) URLConnect 廃止
    038import org.opengion.fukurou.util.HttpConnect;                                   // 6.9.0.0 (2018/01/31) 新規追加
    039import org.opengion.fukurou.system.LogWriter;
    040
    041/**
    042 * ServletContextListener を実装した、コンテキストの監視オブジェクトです。
    043 * これは、コンテキスト(Webアプリケーション)の起動/シャットダウンを監視できる。
    044 *
    045 * ServletContextListener は、
    046 *
    047 *      ConnectionFactory のコネクションプールへのアクセス／開放
    048 *      ResourceFactory   のリソース情報へのアクセス／開放
    049 *
    050 * の作業を行います。
    051 *
    052 * このリスナーは、WEB-INF/web.xml で、組み込みます。
    053 *
    054 * 【WEB-INF/web.xml】
    055 *
    056 *     &lt;listener&gt;
    057 *         &lt;listener-class&gt;
    058 *             org.opengion.hayabusa.common.HybsContextListener
    059 *         &lt;/listener-class&gt;
    060 *     &lt;/listener&gt;
    061 *
    062 * @og.group 初期化
    063 *
    064 * @version  4.0
    065 * @author   Kazuhiko Hasegawa
    066 * @since    JDK5.0,
    067 */
    068@WebListener
    069public class HybsContextListener implements ServletContextListener , ContainerListener {
    070        // 4.0.0.0 (2007/10/26) ConnectionFactoryのhayabusa依存を切るために移動してきた
    071        static {
    072                final Cleanable clr = new Cleanable() {
    073                        /**
    074                         * 初期化(クリア)します。
    075                         * 主に、キャッシュクリアで利用します。
    076                         */
    077                        public void clear() {
    078                                ConnectionFactory.realClose();
    079                        }
    080                };
    081                SystemManager.addCleanable( clr );
    082        }
    083
    084        /**
    085         * デフォルトコンストラクター
    086         *
    087         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
    088         */
    089        public HybsContextListener() { super(); }               // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
    090
    091        /**
    092         *  ServletContextListener インターフェースの実装
    093         *
    094         * Webアプリケーションがリクエストを処理できる状態になったことを
    095         * リスナーに通知する。
    096         *
    097         * @og.rev 3.0.0.0 (2002/12/25) バージョンチェック、HybsSystem初期化追加
    098         * @og.rev 3.4.0.0 (2003/09/01) Contextのpathによる、システムパラメータ の切り替え対応
    099         * @og.rev 3.4.0.3 (2003/09/10) ServletContext の名称を、仮想パス名とする。
    100         * @og.rev 3.5.3.1 (2003/10/31) システムパラメータ ファイルの読み取りタイミングを遅らせます。
    101         * @og.rev 4.0.0.0 (2005/01/31) Ver4 のシステムパラメータ情報の取得処理を追加します。
    102         * @og.rev 4.1.0.1 (2008/01/23) ログ出力先の設定処理を追加
    103         * @og.rev 4.3.4.1 (2008/12/08) ログの環境変数対応
    104         * @og.rev 6.3.8.3 (2015/10/03) プログラムによるWebアプリケーションの拡張
    105         *
    106         * @param  event コンテキストイベント
    107         */
    108        @Override
    109        public void contextInitialized( final ServletContextEvent event ) {
    110                final ServletContext context = event.getServletContext();
    111
    112                final Map<String,String> param = SystemParameter.makeSystemParameter( context );
    113                HybsSystem.setInitialData( param );                     // 4.0.0 (2005/01/31)
    114
    115                // 4.3.4.1 (2008/12/08) ログの環境変数対応
    116                LogWriter.init( HybsSystem.url2dir( System.getProperty( "SYS_LOG_URL" ,HybsSystem.sys( "SYS_LOG_URL" ) ) ) );
    117
    118                // CONTEXT_INITIAL_CALL_URL で登録されたURLを実行します。
    119                // 処理は、contextInitialized が終了してから実行する必要があります。
    120                new Thread( new InitialCallURL() ).start();
    121
    122                System.out.println( "-------" );
    123
    124                // 6.3.8.3 (2015/10/03) プログラムによるWebアプリケーションの拡張
    125        //      addRegistration( context );
    126        }
    127
    128        /**
    129         *  ServletContextListener インターフェースの実装
    130         *
    131         * Webアプリケーションがシャットダウンされることを
    132         * リスナーに通知する。
    133         *
    134         * @og.rev 3.1.1.1 (2003/04/03) キャッシュクリアメソッドを新規追加。
    135         * @og.rev 3.3.3.3 (2003/08/06) HybsTimerTaskManager を終了時にキャンセルするロジックを追加。
    136         * @og.rev 3.5.2.1 (2003/10/27) リンクエラー対策：永続化セッション(SESSIONS.ser)からオブジェクトを削除しておく。
    137         * @og.rev 3.6.0.0 (2004/09/17) CalendarFactory.clear() を追加します。
    138         * @og.rev 4.0.0.0 (2005/01/31) コンテキスト名の取り方を変更します。
    139         * @og.rev 4.0.0.0 (2005/01/31) Cleanable インターフェースによる初期化処理
    140         * @og.rev 4.0.0.0 (2005/01/31) HybsTimerTaskManager は、Cleanable インターフェースによる初期化
    141         * @og.rev 4.1.0.0 (2007/12/27) GE12のクリア処理追加
    142         * @og.rev 4.3.0.0 (2008/07/18) soffice.binのタスクを削除する処理を追加
    143         * @og.rev 5.0.2.0 (2009/11/01) 再編成機能追加
    144         *
    145         * @param  event コンテキストイベント
    146         */
    147        @Override
    148        public void contextDestroyed( final ServletContextEvent event ) {
    149                final String name = HybsSystem.sys( "CONTEXT_NAME" );
    150                System.out.println( "Context Destroyed [" + name + "]  " + new Date() );
    151
    152                // 4.1.0.0 (2007/12/26) GE12からSystemParameterで設定したコンテキスト関係の情報
    153                SystemManager.clearGE12();
    154
    155                // 4.0.0 (2005/01/31) Cleanable インターフェースによる初期化処理
    156                SystemManager.allClear( true ) ;
    157
    158                // 4.3.0.0 (2008/07/18) soffice.binを全てkillします
    159        //      SystemManager.sofficeKill();
    160
    161                SystemManager.sessionDestroyed();               // 3.5.2.1 (2003/10/27)
    162
    163                SystemManager.deleteGUIAccessInfo();    // 5.0.2.0 (2009/11/01)
    164
    165                System.out.println( "-------" );
    166        }
    167
    168        /**
    169         *  ContainerListener インターフェースの実装
    170         *
    171         * セッション固定攻撃対策として、認証の前後でセッションIDが変更されるようになりました。
    172         * セッションIDの変更を検知したい場合は、ContainerListenerを実装する必要があります。
    173         *
    174         * ※ 使い方が分からないので、うまくイベントを拾えていません。
    175         *
    176         * @og.rev 6.3.9.0 (2015/11/06) 新規追加
    177         *
    178         * @param  event コンテナイベント
    179         */
    180        @Override
    181        public void containerEvent( final ContainerEvent event ) {
    182                System.out.println( "【ContainerEvent:" + event.getType() + " : " + event.toString() + "】" );
    183        }
    184
    185        /**
    186         *  ServletContextListener による、ServletやFilter の動的登録。
    187         *
    188         * プログラムによるWebアプリケーションの拡張として、Servlet 3.0 より
    189         * ServletやFilter を、ServletContextListenerのcontexInitializedメソッド から
    190         * 動的に設定できるようになりました。
    191         *
    192         * @og.rev 6.3.8.3 (2015/10/03) プログラムによるWebアプリケーションの拡張
    193         *
    194         * @param  context ServletContextオブジェクト
    195         */
    196        private void addRegistration( final ServletContext context ) {
    197
    198                // web.xml では、filter の定義が先だったので、気持ち、先に設定しておきます。
    199                // ******* Filter *******
    200
    201                // AccessStopFilter             (初期:false)
    202                final FilterRegistration frAS = context.addFilter( "AccessStopFilter", "org.opengion.hayabusa.filter.AccessStopFilter" );
    203                // frAS.setInitParameter( "startTime", "070000" );
    204                // frAS.setInitParameter( "stopTime" , "070000" );
    205                // frAS.setInitParameter( "filename" , "jsp/custom/stopFile.html" );
    206                frAS.addMappingForUrlPatterns( EnumSet.of(DispatcherType.REQUEST ), true, "/jsp/*" );
    207
    208                // GZIPFilter                   (初期:false)
    209                final FilterRegistration frGZ = context.addFilter( "GZIPFilter", "org.opengion.hayabusa.filter.GZIPFilter" );
    210                // frGZ.setInitParameter( "ipAddress", "192.168.,127.0.0.1" );
    211                // frGZ.setInitParameter( "debug"    , "false" );
    212                frGZ.addMappingForUrlPatterns( EnumSet.of(DispatcherType.REQUEST ), true, "/jsp/*" );
    213
    214                // FileFilter                   (初期:false)
    215                final FilterRegistration frFF = context.addFilter( "FileFilter", "org.opengion.hayabusa.filter.FileFilter" );
    216                // frFF.setInitParameter("saveDir", "filetemp/DIR/");
    217                frFF.addMappingForUrlPatterns( EnumSet.of(DispatcherType.REQUEST ), true, "/jsp/*" );
    218
    219                // URLCheckFilter               (初期:false)
    220                final FilterRegistration frUC = context.addFilter( "URLCheckFilter", "org.opengion.hayabusa.filter.URLCheckFilter" );
    221                // frUC.setInitParameter( "filename"  , "jsp/custom/refuseAccess.html" );
    222                // frUC.setInitParameter( "debug"     , "false" );
    223                // frUC.setInitParameter( "ignoreURL" , "" );
    224                frUC.addMappingForUrlPatterns( EnumSet.of(DispatcherType.REQUEST ), true, "/jsp/*" );
    225
    226                // URLHashFilter                (初期:true)
    227                final FilterRegistration frUH = context.addFilter( "URLHashFilter", "org.opengion.hayabusa.filter.URLHashFilter" );
    228                // frUH.setInitParameter( "filename", "jsp/custom/refuseAccess.html" );
    229                // frUH.setInitParameter( "initPage", "/jsp/index.jsp" );
    230                // frUH.setInitParameter( "debug"    , "false" );
    231                frUH.addMappingForUrlPatterns( EnumSet.of(DispatcherType.REQUEST ), true, "*.jsp" );
    232
    233                // ******* Servlet *******
    234
    235                // FileDownload
    236                final ServletRegistration srFD = context.addServlet( "fileDownload", "org.opengion.hayabusa.servlet.FileDownload" );
    237                srFD.addMapping( "/jsp/fileDownload" );
    238
    239                // HybsAdmin
    240                final ServletRegistration srAD = context.addServlet( "admin", "org.opengion.hayabusa.servlet.HybsAdmin" );
    241                srAD.addMapping( "/jsp/admin" );
    242
    243                // MakeImage
    244                final ServletRegistration srMI = context.addServlet( "makeImage", "org.opengion.hayabusa.servlet.MakeImage" );
    245                srMI.addMapping( "/jsp/makeImage" );
    246
    247                // RemoteControlServlet
    248                final ServletRegistration srRC = context.addServlet( "remoteControl", "org.opengion.hayabusa.servlet.RemoteControlServlet" );
    249                srRC.addMapping( "/servlet/remoteControl" );
    250        }
    251
    252        /**
    253         * CONTEXT_INITIAL_CALL_URL を起動する為のスレッド内部クラスです。
    254         *
    255         * HybsContextListener が正常終了しないと、Tomcatが起動したことになっていない為、
    256         * 通常のJSP処理が出来ません。
    257         * ここでは、Tomcat起動時に初期処理URL(CONTEXT_INITIAL_CALL_URL)をコールする為に、
    258         * 時間差を利用する為、スレッド化して実行させます。
    259         * このスレッドは、２秒間スリープ後に、初期処理URLを呼び出します。
    260         *
    261         * @og.rev 4.2.2.0 (2008/05/22) 初期URLの接続ユーザーをシステムリソースより取得
    262         * @og.rev 6.9.0.0 (2018/01/31) URLConnect 廃止、HttpConnect に置き換えます。
    263         * @og.rev 6.9.0.1 (2018/02/05) URL接続エラー時に、LOGだけではわかりにくいので、画面にも出します。
    264         * @og.rev 6.9.0.1 (2018/02/05) URLの値の取り出し時に、{&#064;SYS},{&#064;ENV} の文字列変換を行います。
    265         *
    266         * @og.group ログイン制御
    267         *
    268         * @version  4.0
    269         * @author   Kazuhiko Hasegawa
    270         * @since    JDK5.0,
    271         */
    272        private static final class InitialCallURL implements Runnable {
    273                /**
    274                 * スレッドの処理開始メソッド。
    275                 *
    276                 */
    277                public void run() {
    278                        try {
    279                                Thread.sleep( 2000 );
    280                        }
    281                        catch( final InterruptedException ex) {
    282                                LogWriter.log( "InterruptedException:" + ex.getMessage() );
    283                        }
    284
    285                        final String      name = HybsSystem.sys( "CONTEXT_NAME" );              // 6.9.0.0 (2018/01/31)
    286                        final HybsEntry[] urls = HybsSystem.sysEntry( "CONTEXT_INITIAL_CALL_URL" );
    287                        final String  userPass = HybsSystem.sys( "CONTEXT_INITIAL_CALL_USERPASS" );
    288
    289                        boolean isCall = false;
    290                        if( urls.length > 0 ) {
    291                                for( int i=0; i<urls.length; i++ ) {
    292//                                      final String url = urls[i].getValue();
    293                                        final String url = HybsSystem.changeParam( urls[i].getValue() );                // 6.9.0.1 (2018/02/05) 文字列変換
    294                                        if( url == null || url.isEmpty() ) { continue; }
    295        //                              final URLConnect conn = new URLConnect( url,userPass );
    296                                        final HttpConnect conn = new HttpConnect( url,userPass );                               // 6.9.0.0 (2018/01/31) URLConnect 廃止、HttpConnect に置き換えます。
    297                                        final String msg = "    [" + name + "] URL[" + i + "]:" + url ;                 // 6.9.0.1 (2018/02/05) 共通文字列
    298                                        try {
    299        //                                      conn.connect();
    300        //                                      final String msg = conn.getCode() + ":" + conn.getMessage() ;
    301                                                conn.readData();                                                                                                        // 6.9.0.0 (2018/01/31) 状態を確認する HttpHead は用意していない。GET で代用
    302        //                                      conn.disconnect();
    303//                                              System.out.println( "    [" + name + "] URL[" + i + "]:" + url );
    304        //                                      System.out.println( "           " + msg );
    305                                                System.out.println( msg );                                                                                      // 6.9.0.1 (2018/02/05)
    306                                                System.out.println( "           " + conn.getMessage() );                        // 6.9.0.0 (2018/01/31)
    307                                                isCall = true ;
    308                                        }
    309                                        catch( final IOException ex ) {
    310                                                // 6.9.0.1 (2018/02/05) URL接続エラー時に、LOGだけではわかりにくいので、画面にも出します。
    311//                                              LogWriter.log( "    [" + name + "] URL[" + i + "]:" + url );
    312//                                              LogWriter.log( "           " + ex.getMessage() );
    313
    314                                                final String errMsg = "           " + ex.getMessage();                          // 6.9.0.1 (2018/02/05)
    315                                                LogWriter.log( msg );
    316                                                LogWriter.log( errMsg );
    317                                                LogWriter.log( ex );
    318
    319                                                System.out.println( "    [CONTEXT_INITIAL_CALL_URL Error!]" );
    320                                                System.out.println( msg );
    321                                                System.out.println( errMsg );
    322                                        }
    323                                }
    324                        }
    325                        if( isCall ) {
    326//                              System.out.println( "  CONTEXT_INITIAL_CALL_URL" );
    327                                System.out.println( "    [" + name + "] CONTEXT_INITIAL_CALL_URL" );            // 6.9.0.0 (2018/01/31)
    328                                System.out.println( "-------" );
    329                        }
    330                }
    331        }
    332}