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    }