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.filter;
017
018import org.opengion.fukurou.util.Closer;
019import org.opengion.fukurou.util.HybsDateUtil;
020
021import javax.servlet.ServletRequest;
022import javax.servlet.http.HttpServletRequest;
023import javax.servlet.ServletResponse;
024import javax.servlet.ServletException;
025import javax.servlet.ServletContext;
026import javax.servlet.Filter;
027import javax.servlet.FilterChain;
028import javax.servlet.FilterConfig;
029
030import java.io.File;                                                    // 5.7.3.2 (2014/02/28) Tomcat8 対応
031import java.io.PrintWriter;
032import java.io.BufferedReader;
033import java.io.IOException;
034import java.io.FileInputStream;
035import java.io.InputStreamReader;
036import java.io.UnsupportedEncodingException;
037
038/**
039 * AccessStopFilter は、Filter インターフェースを継承した アクセス制御クラスです。
040 * web.xml で filter 設定することにより、Webアプリケーションへのアクセスを制御できます。
041 * また、SYSTEM ユーザーは、このフィルターを常に通過します。
042 *
043 * フィルターに対してweb.xml でパラメータを設定します。
044 *   ・startTime:停止開始時刻
045 *   ・stopTime :停止終了時刻
046 *   ・filename :停止時メッセージ表示ファイル名
047 *
048 * 【WEB-INF/web.xml】
049 *     <filter>
050 *         <filter-name>AccessStopFilter</filter-name>
051 *         <filter-class>org.opengion.hayabusa.filter.AccessStopFilter</filter-class>
052 *         <init-param>
053 *             <param-name>startTime</param-name>
054 *             <param-value>070000</param-value>
055 *         </init-param>
056 *         <init-param>
057 *             <param-name>stopTime</param-name>
058 *             <param-value>070000</param-value>
059 *         </init-param>
060 *         <init-param>
061 *             <param-name>filename</param-name>
062 *             <param-value>jsp/custom/stopFile.html</param-value>
063 *         </init-param>
064 *     </filter>
065 *
066 *     <filter-mapping>
067 *         <filter-name>AccessStopFilter</filter-name>
068 *         <url-pattern>/jsp/*</url-pattern>
069 *     </filter-mapping>
070 *
071 * @og.group フィルター処理
072 *
073 * @version  4.0
074 * @author   Kazuhiko Hasegawa
075 * @since    JDK5.0,
076 */
077public final class AccessStopFilter implements Filter {
078
079        private static boolean stopFilter = false;
080        private String startTime = "230000";            // 停止開始時刻
081        private String stopTime  = "070000";            // 停止終了時刻
082        private String filename  = null;                        // 停止時メッセージ表示ファイル名
083        private int    startStop = 0;
084
085        /**
086         * フィルター処理本体のメソッドです。
087         *
088         * @og.rev 3.1.3.0 (2003/04/10) UTF-8 決め打ちで、stopFile.html を返送する。
089         * @og.rev 3.1.8.0 (2003/05/16) 文字エンコードが、UTF-8 になっていないのを修正。
090         *
091         * @param       request         ServletRequestオブジェクト
092         * @param       response        ServletResponseオブジェクト
093         * @param       chain           FilterChainオブジェクト
094         * @throws IOException 入出力エラーが発生した場合、throw されます。
095         * @throws ServletException サーブレット関係のエラーが発生した場合、throw されます。
096         */
097        public void doFilter( final ServletRequest request,
098                                                        final ServletResponse response,
099                                                        final FilterChain chain)
100                                                                throws IOException, ServletException {
101
102                if( isStop( request ) ) {
103                        BufferedReader in = null ;
104                        try {
105                                response.setContentType( "text/html; charset=UTF-8" );
106                                PrintWriter out = response.getWriter();
107                                in = new BufferedReader( new InputStreamReader(
108                                                                new FileInputStream( filename ) ,"UTF-8" ) );
109                                String str ;
110                                while( (str = in.readLine()) != null ) {
111                                        out.println( str );
112                                }
113                                out.flush();
114                        }
115                        catch( UnsupportedEncodingException ex ) {
116                                String errMsg = "指定されたエンコーディングがサポートされていません。[UTF-8]" ;
117                                throw new RuntimeException( errMsg,ex );
118                        }
119                        catch( IOException ex ) {
120                                String errMsg = "ストリームがオープン出来ませんでした。[" + filename + "]" ;
121                                throw new RuntimeException( errMsg,ex );
122                        }
123                        finally {
124                                Closer.ioClose( in );
125                        }
126                        return;
127                }
128
129                chain.doFilter(request, response);
130        }
131
132        /**
133         * フィルターの初期処理メソッドです。
134         *
135         * フィルターに対してweb.xml で初期パラメータを設定します。
136         *   ・startTime:停止開始時刻
137         *   ・stopTime :停止終了時刻
138         *   ・filename :停止時メッセージ表示ファイル名
139         *
140         * @og.rev 5.7.3.2 (2014/02/28) Tomcat8 対応。getRealPath( "/" ) の互換性のための修正。
141         *
142         * @param       filterConfig    FilterConfigオブジェクト
143         */
144        public void init(final FilterConfig filterConfig) {
145                ServletContext context = filterConfig.getServletContext();
146                String realPath = context.getRealPath( "" ) + File.separator;   // 5.7.3.2 (2014/02/28) Tomcat8 対応
147
148                startTime = filterConfig.getInitParameter("startTime");
149                stopTime  = filterConfig.getInitParameter("stopTime");
150                filename  = realPath + filterConfig.getInitParameter("filename");
151
152                if( startTime == null || stopTime == null ) {
153                        startStop = 0;
154                }
155                else {
156                        startStop = startTime.compareTo( stopTime );
157                }
158        }
159
160        /**
161         * フィルターの終了処理メソッドです。
162         *
163         */
164        public void destroy() {
165                // ここでは処理を行いません。
166        }
167
168        /**
169         * フィルターの内部状態をチェックするメソッドです。
170         * 内部のフラグをもとに、停止/許可を求めます。
171         *
172         * @og.rev 3.1.8.0 (2003/05/16) 開始時刻と終了時刻を同一にしていると、画面からの制御が効かないバグを修正。
173         * @og.rev 5.5.3.2 (2012/06/08) 通過させるユーザーに、admin を追加します。
174         * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正します。
175         *
176         * @param request ServletRequestオブジェクト
177         *
178         * @return      (true:停止  false:実行許可)
179         */
180        private boolean isStop( final ServletRequest request ) {
181                String userID = ((HttpServletRequest)request).getRemoteUser() ;
182                // 5.5.3.2 (2012/06/08) 通過させるユーザーに、admin を追加
183                if( "SYSTEM".equalsIgnoreCase( userID ) || "admin".equalsIgnoreCase( userID ) ) {
184                        return false;
185                }
186
187                // 4.0.0 (2005/01/31)
188                String time = HybsDateUtil.getDate( "HHmmss" );         // 5.5.7.2 (2012/10/09) HybsDateUtil を利用
189
190                boolean rtnFlag = stopFilter;
191                if( startStop < 0 ) {
192                        if( startTime.compareTo( time ) < 0 &&
193                                time.compareTo( stopTime )  < 0 ) {
194                                        rtnFlag = true;
195                        }
196                }
197                else if( startStop > 0 ) {
198                        if( startTime.compareTo( time ) < 0 ||
199                                time.compareTo( stopTime )  < 0 ) {
200                                        rtnFlag = true;
201                                }
202                }
203                return rtnFlag;
204        }
205
206        /**
207         * フィルターの強制停止/解除を設定するメソッドです。
208         *
209         * @og.rev 4.0.0.0 (2005/01/31) synchronized の廃止
210         *
211         * @param flag (true:停止  false:実行許可)
212         */
213        public static void setStopFilter( final boolean flag ) {
214                stopFilter = flag;
215        }
216
217        /**
218         * フィルターの内部状態(強制停止/解除)を取得するメソッドです。
219         * これは、現在、アクセス制限がどうなっているかという状態ではなく、
220         * 強制停止されているかどうかの確認メソッドです。
221         *
222         * @og.rev 4.0.0.0 (2007/11/29) getStopFilter() ⇒ isStopFilter() に変更
223         *
224         * @return      (true:停止  false:実行許可)
225         */
226        public static boolean isStopFilter() {
227                return stopFilter;
228        }
229
230        /**
231         * 内部状態を文字列で返します。
232         *
233         * @return      このクラスの文字列表示
234         */
235        @Override
236        public String toString() {
237                StringBuilder sb = new StringBuilder();
238                sb.append( "AccessStopFilter" );
239                sb.append( "[" ).append( startTime ).append( "],");
240                sb.append( "[" ).append( stopTime  ).append( "],");
241                sb.append( "[" ).append( filename  ).append( "],");
242                return sb.toString();
243        }
244}