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.hayabusa.common.HybsSystem;
019
020 import java.util.Locale;
021
022 import java.io.File;
023 import java.io.IOException;
024 import java.io.UnsupportedEncodingException;
025 import javax.servlet.ServletRequest;
026 import javax.servlet.ServletResponse;
027 import javax.servlet.ServletContext;
028 import javax.servlet.Filter;
029 import javax.servlet.FilterChain;
030 import javax.servlet.FilterConfig;
031 import javax.servlet.ServletException;
032 import javax.servlet.http.HttpServletRequest;
033 import javax.servlet.http.HttpServletResponse;
034
035 /**
036 * Filter インターフェースを継承した HTML?画面を作?するフィルタクラスです?
037 * web.xml で filter 設定することにより、使用できます?
038 * こ?フィルターでは??常の画面アクセスを行うと、指定?フォル?対して
039 * JSPをHTMLに変換した形で、ファイルをセーブして?ます?こ?HTMLは?
040 * ?サンプル画面として、使用できます?
041 * 出来る限り??画面として使えるように、画面間リンク??ボタン制御?
042 * JavaScript を挿入する事で実現して?す?
043 *
044 * フィルターに対してweb.xml でパラメータを設定します?
045 * ・saveDir :ファイルをセーブするディレクトリ
046 *
047 * パラメータがな??合?、G:/webapps/作番/filetemp/DIR/ 以下に自動設定されます?
048 * また??レクトリが?相対パスの場合?、G:/webapps/作番/ 以下に、絶対パスの
049 * 場合?、そのパスの下に作?されます? *
050 *
051 * 【WEB-INF/web.xml?
052 * <filter>
053 * <filter-name>FileFilter</filter-name>
054 * <filter-class>org.opengion.hayabusa.filter.FileFilter</filter-class>
055 * <init-param>
056 * <param-name>saveDir</param-name>
057 * <param-value>filetemp/DIR/</param-value>
058 * </init-param>
059 * </filter>
060 *
061 * <filter-mapping>
062 * <filter-name>FileFilter</filter-name>
063 * <url-pattern>/jsp/*</url-pattern>
064 * </filter-mapping>
065 *
066 * @og.group フィルター処?
067 *
068 * @version 4.0
069 * @author Kazuhiko Hasegawa
070 * @since JDK5.0,
071 */
072 public class FileFilter implements Filter {
073 private String saveDir = null; // "G:/webapps/gf/filetemp/DIR/" など
074
075 /**
076 * Filter インターフェースの doFilter メソ?
077 *
078 * Filter クラスの doFilter メソ?はコン?により呼び出され???チェーンにおけ?
079 * リソースへのクライアントリクエスト?ために?毎回リクエスト?レスポンスのペアが?
080 * チェーンを?して渡されます? こ?メソ?に渡され?FilterChain を利用して、Filter ?
081 * リクエストやレスポンスをチェーン??次のエン??(Filter)にリクエストとレスポンス?
082 * 渡す事ができます?
083 * こ?メソ?の典型的な実??以下?ようなパターンとなるでしょ??
084 * 1. リクエスト?検査
085 * 2. オプションとして、?力フィルタリング用にコン??しくはヘッ?フィルタリング
086 * するためにカスタ??よるリクエストオブジェクト?ラ??
087 * 3. オプションとして、?力フィルタリング用にコン??しくはヘッ?フィルタリング
088 * するためにカスタ??よるレスポンスオブジェクトラ??
089 * 4. 以下? a)、b) のどちらか
090 * a) FileterChain オブジェク?chain.doFilter()) を利用してチェーンの次のエン??を呼び出?
091 * b) リクエスト??止めるために、リクエスト?レスポンスのペアをフィルタチェーンの次の
092 * エン??に渡さな?
093 * 5. フィルタチェーンの次のエン??の呼び出した後?直接レスポンスのヘッ?セ?
094 *
095 * @param req ServletRequestオブジェク?
096 * @param res ServletResponseオブジェク?
097 * @param chain FilterChainオブジェク?
098 * @throws IOException
099 * @throws ServletException
100 */
101 public void doFilter( final ServletRequest req,
102 final ServletResponse res,
103 final FilterChain chain )
104 throws IOException, ServletException {
105 if(req instanceof HttpServletRequest && res instanceof HttpServletResponse) {
106 HttpServletRequest request = (HttpServletRequest) req;
107 HttpServletResponse response = (HttpServletResponse) res;
108
109 try {
110 request.setCharacterEncoding( "UTF-8" );
111 }
112 catch ( UnsupportedEncodingException ex ) {
113 throw new RuntimeException( ex );
114 }
115
116 String filename = makeFileName( request );
117 if( filename != null ) {
118 FileResponseWrapper wrappedResponse = new FileResponseWrapper(response,filename);
119 chain.doFilter(req, wrappedResponse);
120 wrappedResponse.finishResponse();
121 }
122 else {
123 chain.doFilter(req, res);
124 }
125 }
126 }
127
128 /**
129 * フィルターの初期処?ソ?です?
130 *
131 * フィルターに対してweb.xml で初期パラメータを設定します?
132 * ・startTime:停止開始時刻
133 * ・stopTime :停止終?刻
134 * ・filename :停止時メ?ージ表示ファイル?
135 *
136 * @param filterConfig FilterConfigオブジェク?
137 */
138 public void init(final FilterConfig filterConfig) {
139 ServletContext context = filterConfig.getServletContext();
140 String realPath = context.getRealPath( "/" );
141
142 String dir = filterConfig.getInitParameter("saveDir");
143 if( dir != null && dir.length() > 1 ) {
144 dir = dir.replace( '\\','/' );
145 if( dir.charAt(0) == '/' || dir.charAt(1) == ':' ) {
146 saveDir = dir;
147 }
148 else {
149 saveDir = realPath + dir ;
150 }
151
152 if( dir.charAt(dir.length()-1) != '/' ) {
153 saveDir = saveDir + "/" ;
154 }
155 }
156 else {
157 saveDir = realPath + "filetemp/DIR/" ;
158 }
159 }
160
161 /**
162 * Filter インターフェースの destroy メソ? (何もしません)?
163 *
164 * サービス状態を終えた事を Filter に伝えるために Web コン?が呼び出します?
165 * Filter の doFilter メソ?が終?たか、タイ?ウトに達した?てのスレ?において?
166 * こ?メソ?を??呼び出されます? Web コン?がこのメソ?を呼び出した後??
167 * Filter のこ?インスタンスにおいて二度と doFilter メソ?を呼び出す事?ありません?
168 *
169 * こ?メソ?は、フィルタに保持されて?(例えば、メモリ、ファイルハンドル、スレ?)
170 * 様?なリソースを開放する機会を与え?あら?永続?の状態が、メモリ上におけ?Filter
171 * の現在の状態と同期して?ように注意してください?
172 */
173 public void destroy() {
174 // noop
175 }
176
177 /**
178 * セーブするファイル名を、リクエスト情報より取得します?
179 *
180 * リクエストされたファイル(.jsp)を?HTMLファイル(.htm)にする?でなく?
181 * 呼び出されたとき? command を?に、ファイル名を作?します?
182 * command="NEW" + forward.jsp ? "forward.htm"
183 * command="RENEW" + forward.jsp ? "renew.htm"
184 * command="日本語名+ forward.jsp ? "コマンド名.htm"
185 * command="日本語名+ update.jsp ? "コマンド名.htm"
186 * command="NEW" + index.jsp ? "indexNW.htm"
187 * command="RENEW" + index.jsp ? "indexRNW.htm"
188 * command="NEW" + query.jsp ? "queryNW.htm"
189 * command="NEW" + resultXX.jsp ? "forwardXX.htm" 5.6.3.4 (2013/04/26) result.jsp にフレー?使?ターン(??イン)
190 * matrixMenu対?
191 * URI? URI? request取?
192 * ?gamenId="jsp" + index.jsp + GAMENID=XXXX ?saveDir + "jsp/indexXXXX.htm" Matrixメニューからの画面呼出し?
193 * ② gamenId="jsp" + result.jsp + GAMENID=XXXX ?saveDir + "XXXX/index.htm" 画面QUERYのヘッ??メニュー
194 * ③ gamenId="jsp" + index.jsp + group=YYYY ?saveDir + "jsp/indexYYYY.htm" ?存在しな??ず?
195 * ④ gamenId="menu" + multiMenu.jsp + GAMENID=XXXX ?saveDir + "jsp/menuXXXX.htm" ?存在しな??ず?
196 * ⑤ gamenId="menu" + multiMenu.jsp + group=YYYY ?saveDir + "jsp/menuYYYY.htm" 通常メニューのグループ選?
197 * ⑥ gamenId="menu" + matrixMenu.jsp + group=YYYY ?saveDir + "menu/matrixMenuYYYY.htm" Matrixメニューのグループ選?
198 * <del>GAMENID=XXXX&buttonRequest=true + index.jsp ?"jsp/indexXXXX.htm"</del>
199 * <del>GAMENID=XXXX&buttonRequest=true + multiMenu.jsp ?"jsp/menuXXXX.htm"</del>
200 * そ?? xxxx.jsp ? "xxxx.htm"
201 *
202 * こ?メソ?は、フィルタに保持されて?(例えば、メモリ、ファイルハンドル、スレ?)
203 * 様?なリソースを開放する機会を与え?あら?永続?の状態が、メモリ上におけ?Filter
204 * の現在の状態と同期して?ように注意してください?
205 *
206 * @og.rev 4.0.0.0 (2007/11/28) メソ?の戻り?をチェ?します?
207 * @og.rev 4.3.3.0 (2008/10/01) Matrixメニュー対?
208 * @og.rev 5.5.2.5 (2012/05/21) update.jsp に出力されるファイルを?コマンド名.htm に出力するよ?機?追?
209 * @og.rev 5.6.3.4 (2013/04/26) 5.6.3.4 (2013/04/26) command="NEW" + resultXX.jsp ? "forwardXX.htm"?result.jsp にフレー?使?ターン(??イン)
210 * @og.rev 5.6.4.2 (2013/05/17) Matrixメニュー buttonRequest ?対?
211 *
212 * @param request ServletRequestオブジェク?
213 *
214 * @return セーブするファイル?
215 */
216 private String makeFileName( final ServletRequest request ) {
217 HttpServletRequest myReq = (HttpServletRequest) request;
218 String requestURI = myReq.getRequestURI();
219
220 int index2 = requestURI.lastIndexOf( '/' );
221 String jspID = requestURI.substring( index2+1 );
222 int index1 = requestURI.lastIndexOf( '/',index2-1 );
223 String gamenId = requestURI.substring( index1+1,index2 );
224
225 String file = null;
226
227 if( jspID != null && jspID.endsWith( ".jsp" ) ) {
228 String cmd = request.getParameter( "command" );
229 if( cmd != null && jspID.equals( "forward.jsp" ) ) {
230 if( "NEW".equals( cmd ) ) { file = "forward.htm"; }
231 else if( "RENEW".equals( cmd ) || "REVIEW".equals( cmd ) ) { file = "renew.htm"; }
232 else {
233 String xferVal = request.getParameter( HybsSystem.NO_XFER_KEY + cmd );
234 // 5.5.2.5 (2012/05/21) update.jsp に出力されるファイルを?コマンド名.htm に出力するよ?機?追?
235 if( "update.jsp".equals( xferVal ) ) {
236 file = cmd + ".htm" ;
237 }
238 else if( xferVal != null && xferVal.endsWith( "jsp" ) ) {
239 file = xferVal.toLowerCase(Locale.JAPAN).replace( "jsp","htm" );
240 }
241 else {
242 String xferCmd = request.getParameter( HybsSystem.NO_XFER_KEY + cmd + "CMD" );
243 if( xferCmd != null ) {
244 file = xferCmd.toLowerCase(Locale.JAPAN) + ".htm";
245 }
246 else {
247 file = cmd.toLowerCase(Locale.JAPAN) + ".htm";
248 }
249 }
250 }
251 }
252 else if( "index.jsp".equals( jspID ) && ( "RENEW".equals( cmd ) || "REVIEW".equals( cmd ) ) ) {
253 file = "indexRNW.htm";
254 }
255 else if( "index.jsp".equals( jspID ) && "NEW".equals( cmd ) ) {
256 file = "indexNW.htm";
257 }
258 else if( "query.jsp".equals( jspID ) && "NEW".equals( cmd ) ) {
259 file = "queryNW.htm";
260 }
261 // 5.6.3.4 (2013/04/26) command="NEW" + resultXX.jsp ? "forwardXX.htm"?result.jsp にフレー?使?ターン(??イン)
262 // else if( jspID.startsWith( "result" ) && jspID.endsWith( ".jsp" ) && "NEW".equals( cmd ) ) {
263 else if( jspID.startsWith( "result" ) && "NEW".equals( cmd ) ) {
264 file = "forward" + jspID.substring( 6,jspID.length()-4 ) + ".htm" ;
265 }
266 // 5.6.4.2 (2013/05/17) fileDownload.jsp の対?
267 else if( "fileDownload.jsp".equals( jspID ) ) {
268 gamenId = request.getParameter( "GAMENID" ); // gamenId(??フォル?抽出)をリクエスト変数から取得する?
269 file = request.getParameter( "filename" ); // 日本語ファイル名で抽出する場合?
270 file = "fileDownload:" + file ; // ただし?セーブ時は、UnicodeLittle なので?fileDownload:" でマ?カーする?
271 }
272 else {
273 file = jspID.substring( 0,jspID.length()-4 ) + ".htm" ;
274 }
275
276 // 5.6.4.2 (2013/05/17) Matrixメニュー 対?
277 // URI? URI? request取?
278 // ?gamenId="jsp" + index.jsp + GAMENID=XXXX ?saveDir + "jsp/indexXXXX.htm" Matrixメニューからの画面呼出し?
279 // ② gamenId="jsp" + result.jsp + GAMENID=XXXX ?saveDir + "jsp/indexXXXX.htm" 画面QUERYのヘッ??メニュー
280 // ③ gamenId="menu" + multiMenu.jsp + group=YYYY ?saveDir + "menu/menuYYYY.htm" 通常メニューのグループ選?
281 // ④ gamenId="menu" + matrixMenu.jsp + group=YYYY ?saveDir + "menu/matrixMenuYYYY.htm" Matrixメニューのグループ選?
282 String guiKey = request.getParameter( "GAMENID" );
283 String group = request.getParameter( "group" );
284
285 if( "jsp".equals( gamenId ) && guiKey != null ) {
286 if( "index.jsp".equals( jspID ) || "result.jsp".equals( jspID ) ) {
287 file = "jsp/index" + guiKey + ".htm"; // ?②
288 }
289 }
290 else if( group != null ) {
291 if( "multiMenu.jsp".equals( jspID ) ) {
292 file = gamenId + "/menu" + group + ".htm"; // ③
293 }
294 else if( "matrixMenu.jsp".equals( jspID ) ) {
295 file = gamenId + "/matrixMenu" + group + ".htm"; // ④
296 }
297 gamenId = "jsp" ; // トリ?ー
298 }
299
300 // 5.6.4.2 (2013/05/17) Matrixメニュー buttonRequest ?
301 // // 4.3.3.0 (2008/10/01) Matrixメニュー対?
302 // // GAMENID=XXXX&buttonRequest=true + index.jsp ?"jsp/indexXXXX.htm"
303 // // GAMENID=XXXX&buttonRequest=true + multiMenu.jsp ?"jsp/menuXXXX.htm"
304 // // group=YYYY&buttonRequest=true + matrixMenu.jsp ?"menu/matrixMenuYYYY.htm"
305 // String guiKey = request.getParameter( "GAMENID" );
306 // String btnReq = request.getParameter( "buttonRequest" );
307 // if( "true".equals( btnReq ) ) {
308 // if( guiKey != null ) {
309 // if( "index.jsp".equals( jspID ) ) {
310 // file = "jsp/index" + guiKey + ".htm";
311 // }
312 // else if( "multiMenu.jsp".equals( jspID ) ) {
313 // file = "jsp/menu" + guiKey + ".htm";
314 // gamenId = "jsp" ; // トリ?ー
315 // }
316 // }
317 // else {
318 //
319 // String group = request.getParameter( "group" );
320 // if( group != null ) {
321 // if( "matrixMenu.jsp".equals( jspID ) ) {
322 // file = "menu/matrixMenu" + group + ".htm";
323 // gamenId = "jsp" ; // トリ?ー
324 // }
325 // }
326 // }
327 // }
328
329 // int index1 = requestURI.lastIndexOf( '/',index2-1 );
330 // String gamenId = requestURI.substring( index1+1,index2 );
331
332 if( "jsp".equals( gamenId ) ) { file = saveDir + file; }
333 else { file = saveDir + gamenId + "/" + file; }
334
335 // File fl = new File( saveDir + gamenId );
336 // if( !fl.exists() && !fl.mkdirs() ) {
337 File fl = new File( file ).getParentFile();
338 if( fl != null && !fl.exists() && !fl.mkdirs() ) {
339 String errMsg = "??フォル?作?できませんでした?" + fl + "]" ;
340 throw new RuntimeException( errMsg );
341 }
342 }
343
344 return file;
345 }
346 }