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 }