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 */
016 package org.opengion.hayabusa.filter;
017
018 import org.opengion.fukurou.util.StringUtil;
019
020 import java.io.IOException;
021 import javax.servlet.ServletRequest;
022 import javax.servlet.ServletResponse;
023 import javax.servlet.Filter;
024 import javax.servlet.FilterChain;
025 import javax.servlet.FilterConfig;
026 import javax.servlet.ServletException;
027 import javax.servlet.http.HttpServletRequest;
028 import javax.servlet.http.HttpServletResponse;
029
030 /**
031 * GZIPFilter は、Filter インターフェースを継承した ZIP圧縮クラスです?
032 * web.xml で filter 設定することにより、Webアプリケーションへのアクセスを制御できます?
033 * フィルタへのパラメータは、IPAddress と Debug を指定できます?
034 * IPAddress は、リモートユーザーのIPアドレスをカンマ区?で??できます?
035 * これは、カンマ区?で?した後?アクセス??アドレスの先???の???
036 * 判定して?す?
037 *
038 * フィルターに対してweb.xml でパラメータを設定します?
039 * <ul>
040 * <li>IPAddress :フィルタするリモー?Pアドレス。無?時は、ZIP圧縮しません?/li>
041 * <li>Debug :フィルタ処??詳細??を?力します?(??モー?</li>
042 * </ul>
043 *
044 *<pre>
045 * 【WEB-INF/web.xml?
046 * <filter>
047 * <filter-name>GZIPFilter</filter-name>
048 * <filter-class>org.opengion.hayabusa.filter.GZIPFilter</filter-class>
049 * <init-param>
050 * <param-name>ipAddress</param-name>
051 * <param-value>200.1</param-value>
052 * </init-param>
053 * <init-param>
054 * <param-name>debug</param-name>
055 * <param-value>true</param-value>
056 * </init-param>
057 * </filter>
058 *
059 * <filter-mapping>
060 * <filter-name>GZIPFilter</filter-name>
061 * <url-pattern>/jsp/*</url-pattern>
062 * </filter-mapping>
063 *</pre>
064 *
065 * @version 4.0
066 * @author Kazuhiko Hasegawa
067 * @since JDK5.0,
068 */
069 public class GZIPFilter implements Filter {
070 private String[] ipaddrArray = null;
071 private boolean isDebug = false;
072
073 /**
074 * Filter インターフェースの doFilter メソ?
075 *
076 * Filter クラスの doFilter メソ?はコン?により呼び出され???チェーンにおけ?
077 * リソースへのクライアントリクエスト?ために?毎回リクエスト?レスポンスのペアが?
078 * チェーンを?して渡されます? こ?メソ?に渡され?FilterChain を利用して、Filter ?
079 * リクエストやレスポンスをチェーン??次のエン??(Filter)にリクエストとレスポンス?
080 * 渡す事ができます?
081 * こ?メソ?の典型的な実??以下?ようなパターンとなるでしょ??
082 * 1. リクエスト?検査
083 * 2. オプションとして、?力フィルタリング用にコン??しくはヘッ?フィルタリング
084 * するためにカスタ??よるリクエストオブジェクト?ラ??
085 * 3. オプションとして、?力フィルタリング用にコン??しくはヘッ?フィルタリング
086 * するためにカスタ??よるレスポンスオブジェクトラ??
087 * 4. 以下? a)、b) のどちらか
088 * a) FileterChain オブジェク?chain.doFilter()) を利用してチェーンの次のエン??を呼び出?
089 * b) リクエスト??止めるために、リクエスト?レスポンスのペアをフィルタチェーンの次の
090 * エン??に渡さな?
091 * 5. フィルタチェーンの次のエン??の呼び出した後?直接レスポンスのヘッ?セ?
092 *
093 * @param req ServletRequestオブジェク?
094 * @param res ServletResponseオブジェク?
095 * @param chain FilterChainオブジェク?
096 * @throws IOException 入出力エラーが発生したと?
097 * @throws ServletException サーブレ?関係?エラーが発生した?合?throw されます?
098 */
099 public void doFilter( final ServletRequest req,
100 final ServletResponse res,
101 final FilterChain chain )
102 throws IOException, ServletException {
103 if( req instanceof HttpServletRequest && res instanceof HttpServletResponse ) {
104 HttpServletRequest request = (HttpServletRequest) req;
105 HttpServletResponse response = (HttpServletResponse) res;
106 if( isFiltering( request ) ) {
107 GZIPResponseWrapper wrappedResponse = new GZIPResponseWrapper(response);
108 chain.doFilter(req, wrappedResponse);
109 wrappedResponse.finishResponse();
110 return;
111 }
112 }
113 chain.doFilter(req, res);
114 }
115
116 /**
117 * フィルター処??判?
118 *
119 * フィルター処?行うかど?を判定します?
120 * ipAddress と前方??するリモートクライアントから?アクセス時に?
121 * GZIPフィルタリング処?行います?
122 *
123 * @param request HttpServletRequestオブジェク?
124 *
125 * @return フィルター処?行うかど?[true:フィルタ対象/false:非対象]
126 */
127 private boolean isFiltering( final HttpServletRequest request ) {
128
129 boolean isFilter = false;
130
131 String ae = request.getHeader("accept-encoding");
132 String uri = request.getRequestURI();
133 String adrs = request.getRemoteAddr();
134
135 // ブラウザ?GZIP 対応かど?
136 if( ae != null && ae.indexOf("gzip") >= 0 ) {
137 // リクエストが、jsp,js,css かど?
138 if( uri.endsWith(".jsp") || uri.endsWith(".js") || uri.endsWith(".css") ) {
139 // アドレスが???アドレス配?で先???して?かど?
140 for( int i=0; i<ipaddrArray.length; i++ ) {
141 if( adrs.startsWith( ipaddrArray[i] ) ) {
142 isFilter = true; // ??
143 break;
144 }
145 }
146 }
147 }
148
149 if( isDebug ) {
150 System.out.println("[Filtering " + isFilter + "]");
151 System.out.println(" IP Address :" + adrs );
152 System.out.println(" Request URI:" + uri );
153 }
154
155 return isFilter;
156 }
157
158 /**
159 * Filter インターフェースの init メソ? (何もしません)?
160 *
161 * Web コン?は、Filter をサービス状態にするために init メソ?を呼び出します?
162 * Servlet コン?は、Filter をインスタンス化したあと??? init メソ?を呼び出します?
163 * Filter がフィルタリングの仕事を依?される前に、init メソ?は正常に完?てなければ?ません?
164 *
165 * init メソ?が以下?ような状況になると、Web コン?は Filter をサービス状態にできません?
166 * 1. ServletException をスローした
167 * 2. Web コネクタで定義した時間?戻らな?
168 *
169 * @param filterConfig FilterConfigオブジェク?
170 */
171 public void init(final FilterConfig filterConfig) {
172 ipaddrArray = StringUtil.csv2Array( filterConfig.getInitParameter("ipAddress") );
173 isDebug = Boolean.valueOf( filterConfig.getInitParameter("debug") ).booleanValue();
174 }
175
176 /**
177 * Filter インターフェースの destroy メソ? (何もしません)?
178 *
179 * サービス状態を終えた事を Filter に伝えるために Web コン?が呼び出します?
180 * Filter の doFilter メソ?が終?たか、タイ?ウトに達した?てのスレ?において?
181 * こ?メソ?を??呼び出されます? Web コン?がこのメソ?を呼び出した後??
182 * Filter のこ?インスタンスにおいて二度と doFilter メソ?を呼び出す事?ありません?
183 *
184 * こ?メソ?は、フィルタに保持されて?(例えば、メモリ、ファイルハンドル、スレ?)
185 * 様?なリソースを開放する機会を与え?あら?永続?の状態が、メモリ上におけ?Filter
186 * の現在の状態と同期して?ように注意してください?
187 */
188 public void destroy() {
189 // noop
190 }
191 }