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 *     <listener>
057 *         <listener-class>
058 *             org.opengion.hayabusa.common.HybsContextListener
059 *         </listener-class>
060 *     </listener>
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         * このスレッドは、2秒間スリープ後に、初期処理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}