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 サーブレãƒ?ƒˆ関係ã?エラーが発生したå?合ã?throw されますã?
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             * @og.rev 5.7.3.2 (2014/02/28) Tomcat8 対応ã?getRealPath( "/" ) の互換性のための修正ã€?
137             *
138             * @param filterConfig FilterConfigオブジェクãƒ?
139             */
140            public void init(final FilterConfig filterConfig) {
141                    ServletContext context = filterConfig.getServletContext();
142    //              String realPath = context.getRealPath( "/" );
143                    String realPath = context.getRealPath( "" ) + File.separator;   // 5.7.3.2 (2014/02/28) Tomcat8 対å¿?
144    
145                    String dir = filterConfig.getInitParameter("saveDir");
146                    if( dir != null && dir.length() > 1 ) {
147                            dir = dir.replace( '\\','/' );
148                            if( dir.charAt(0) == '/' || dir.charAt(1) == ':' ) {
149                                    saveDir = dir;
150                            }
151                            else {
152                                    saveDir = realPath + dir ;
153                            }
154    
155                            if( dir.charAt(dir.length()-1) != '/' ) {
156                                    saveDir = saveDir + "/" ;
157                            }
158                    }
159                    else {
160                            saveDir = realPath + "filetemp/DIR/" ;
161                    }
162            }
163    
164            /**
165             * Filter インターフェースの destroy メソãƒ?ƒ‰ (何もしません)ã€?
166             *
167             * サービス状態を終えた事を Filter に伝えるために Web コンãƒ?ƒŠが呼び出しますã?
168             * Filter の doFilter メソãƒ?ƒ‰が終äº?�—たか、タイãƒ?‚¢ウトに達したå?てのスレãƒ?ƒ‰においてã€?
169             * こã?メソãƒ?ƒ‰をä¸?º¦ã�?�‘呼び出されますã? Web コンãƒ?ƒŠがこのメソãƒ?ƒ‰を呼び出した後ã?ã€?
170             * Filter のこã?インスタンスにおいて二度と doFilter メソãƒ?ƒ‰を呼び出す事ã?ありませんã€?
171             *
172             * こã?メソãƒ?ƒ‰は、フィルタに保持されてã�?‚‹(例えば、メモリ、ファイルハンドル、スレãƒ?ƒ‰)
173             * 様ã?なリソースを開放する機会を与えã€?あらã‚?‚‹永続æ?の状態が、メモリ上におけã‚?Filter
174             * の現在の状態と同期してã�?‚‹ように注意してくださいã€?
175             */
176            public void destroy() {
177                    // noop
178            }
179    
180            /**
181             * セーブするファイル名を、リクエスト情報より取得しますã?
182             *
183             * リクエストされたファイル(.jsp)をã?HTMLファイル(.htm)にするã�?�‘でなくã?
184             * 呼び出されたときã? command をå?に、ファイル名を作æ?しますã?
185             *   command="NEW"    + forward.jsp � "forward.htm"
186             *   command="RENEW"  + forward.jsp � "renew.htm"
187             *   command="日本語名+ forward.jsp â‡? "コマンド名.htm"
188             *   command="日本語名+ update.jsp  â‡? "コマンド名.htm"
189             *   command="NEW"    + index.jsp   � "indexNW.htm"
190             *   command="RENEW"  + index.jsp   � "indexRNW.htm"
191             *   command="NEW"    + query.jsp   � "queryNW.htm"
192             *   command="NEW"    + resultXX.jsp â‡? "forwardXX.htm"                 5.6.3.4 (2013/04/26) result.jsp にフレーãƒ?‚’使ã�?ƒ‘ターン(?“ã?イン)
193             *   matrixMenu対å¿?
194             *                 URIåˆ?›¢          URIåˆ?›¢           request取å?
195             *              â‘?gamenId="jsp"  + index.jsp       + GAMENID=XXXX  â‡?saveDir + "jsp/indexXXXX.htm"         Matrixメニューからの画面呼出しã?
196             *              ② gamenId="jsp"  + result.jsp      + GAMENID=XXXX  â‡?saveDir + "XXXX/index.htm"            画面QUERYのヘッãƒ??メニュー
197             *              ③ gamenId="jsp"  + index.jsp       + group=YYYY    â‡?saveDir + "jsp/indexYYYY.htm"         ?ˆ存在しなã�??ずï¼?
198             *              ④ gamenId="menu" + multiMenu.jsp   + GAMENID=XXXX  â‡?saveDir + "jsp/menuXXXX.htm"          ?ˆ存在しなã�??ずï¼?
199             *              ⑤ gamenId="menu" + multiMenu.jsp   + group=YYYY    â‡?saveDir + "jsp/menuYYYY.htm"          通常メニューのグループ選æŠ?
200             *              ⑥ gamenId="menu" + matrixMenu.jsp  + group=YYYY    â‡?saveDir + "menu/matrixMenuYYYY.htm"   Matrixメニューのグループ選æŠ?
201             *   そã?ä»?            xxxx.jsp    â‡? "xxxx.htm"
202             *
203             * こã?メソãƒ?ƒ‰は、フィルタに保持されてã�?‚‹(例えば、メモリ、ファイルハンドル、スレãƒ?ƒ‰)
204             * 様ã?なリソースを開放する機会を与えã€?あらã‚?‚‹永続æ?の状態が、メモリ上におけã‚?Filter
205             * の現在の状態と同期してã�?‚‹ように注意してくださいã€?
206             *
207             * @og.rev 4.0.0.0 (2007/11/28) メソãƒ?ƒ‰の戻りå?をチェãƒ?‚¯しますã?
208             * @og.rev 4.3.3.0 (2008/10/01) Matrixメニュー対å¿?
209             * @og.rev 5.5.2.5 (2012/05/21) update.jsp に出力されるファイルをã?コマンド名.htm に出力するよã�?�«機è?追åŠ?
210             * @og.rev 5.6.3.4 (2013/04/26) 5.6.3.4 (2013/04/26) command="NEW" + resultXX.jsp â‡? "forwardXX.htm"ã€?result.jsp にフレーãƒ?‚’使ã�?ƒ‘ターン(?“ã?イン)
211             * @og.rev 5.6.4.2 (2013/05/17) Matrixメニュー buttonRequest å»?­¢対å¿?
212             *
213             * @param request ServletRequestオブジェクãƒ?
214             *
215             * @return      セーブするファイルå�?
216             */
217            private String makeFileName( final ServletRequest request ) {
218                    HttpServletRequest myReq = (HttpServletRequest) request;
219                    String requestURI = myReq.getRequestURI();
220    
221                    int index2     = requestURI.lastIndexOf( '/' );
222                    String jspID   = requestURI.substring( index2+1 );
223                    int index1     = requestURI.lastIndexOf( '/',index2-1 );
224                    String gamenId = requestURI.substring( index1+1,index2 );
225    
226                    String file = null;
227    
228                    if( jspID != null && jspID.endsWith( ".jsp" ) ) {
229                            String cmd = request.getParameter( "command" );
230                            if( cmd != null && jspID.equals( "forward.jsp" ) ) {
231                                    if( "NEW".equals( cmd ) ) { file = "forward.htm"; }
232                                    else if( "RENEW".equals( cmd ) || "REVIEW".equals( cmd ) ) { file = "renew.htm"; }
233                                    else {
234                                            String xferVal = request.getParameter( HybsSystem.NO_XFER_KEY + cmd );
235                                            // 5.5.2.5 (2012/05/21) update.jsp に出力されるファイルをã?コマンド名.htm に出力するよã�?�«機è?追åŠ?
236                                            if( "update.jsp".equals( xferVal ) ) {
237                                                    file = cmd + ".htm" ;
238                                            }
239                                            else if( xferVal != null && xferVal.endsWith( "jsp" ) ) {
240                                                    file = xferVal.toLowerCase(Locale.JAPAN).replace( "jsp","htm" );
241                                            }
242                                            else {
243                                                    String xferCmd = request.getParameter( HybsSystem.NO_XFER_KEY + cmd + "CMD" );
244                                                    if( xferCmd != null ) {
245                                                            file = xferCmd.toLowerCase(Locale.JAPAN) + ".htm";
246                                                    }
247                                                    else {
248                                                            file = cmd.toLowerCase(Locale.JAPAN) + ".htm";
249                                                    }
250                                            }
251                                    }
252                            }
253                            else if( "index.jsp".equals( jspID ) && ( "RENEW".equals( cmd ) || "REVIEW".equals( cmd ) ) ) {
254                                    file = "indexRNW.htm";
255                            }
256                            else if( "index.jsp".equals( jspID ) && "NEW".equals( cmd ) ) {
257                                    file = "indexNW.htm";
258                            }
259                            else if( "query.jsp".equals( jspID ) && "NEW".equals( cmd ) ) {
260                                    file = "queryNW.htm";
261                            }
262                            // 5.6.3.4 (2013/04/26) command="NEW" + resultXX.jsp â‡? "forwardXX.htm"ã€?result.jsp にフレーãƒ?‚’使ã�?ƒ‘ターン(?“ã?イン)
263    //                      else if( jspID.startsWith( "result" ) && jspID.endsWith( ".jsp" ) && "NEW".equals( cmd ) ) {
264                            else if( jspID.startsWith( "result" ) && "NEW".equals( cmd ) ) {
265                                    file = "forward" + jspID.substring( 6,jspID.length()-4 ) + ".htm" ;
266                            }
267                            // 5.6.4.2 (2013/05/17) fileDownload.jsp の対å¿?
268                            else if( "fileDownload.jsp".equals( jspID ) ) {
269                                    gamenId = request.getParameter( "GAMENID" );    // gamenId(å…??フォルãƒ?‚’抽出)をリクエスト変数から取得するã?
270                                    file    = request.getParameter( "filename" );   // 日本語ファイル名で抽出する場合ã?
271                                    file    = "fileDownload:" + file ;                              // ただしã?セーブ時は、UnicodeLittle なのでã€?fileDownload:" でマã?カーするã€?
272                            }
273                            else {
274                                    file = jspID.substring( 0,jspID.length()-4 ) + ".htm" ;
275                            }
276    
277                            // 5.6.4.2 (2013/05/17) Matrixメニュー 対å¿?
278                            //    URIåˆ?›¢          URIåˆ?›¢           request取å?
279                            // â‘?gamenId="jsp"  + index.jsp       + GAMENID=XXXX  â‡?saveDir + "jsp/indexXXXX.htm"         Matrixメニューからの画面呼出しã?
280                            // ② gamenId="jsp"  + result.jsp      + GAMENID=XXXX  â‡?saveDir + "jsp/indexXXXX.htm"         画面QUERYのヘッãƒ??メニュー
281                            // ③ gamenId="menu" + multiMenu.jsp   + group=YYYY    â‡?saveDir + "menu/menuYYYY.htm"         通常メニューのグループ選æŠ?
282                            // ④ gamenId="menu" + matrixMenu.jsp  + group=YYYY    â‡?saveDir + "menu/matrixMenuYYYY.htm"   Matrixメニューのグループ選æŠ?
283                            String guiKey = request.getParameter( "GAMENID" );
284                            String group  = request.getParameter( "group" );
285    
286                            if( "jsp".equals( gamenId ) && guiKey != null ) {
287                                    if( "index.jsp".equals( jspID ) || "result.jsp".equals( jspID ) ) {
288                                            file = "jsp/index" + guiKey + ".htm";                           // â‘?②
289                                    }
290                            }
291                            else if( group != null ) {
292                                    if( "multiMenu.jsp".equals( jspID ) ) {
293                                            file = gamenId + "/menu" + group + ".htm";                      // ③
294                                    }
295                                    else if( "matrixMenu.jsp".equals( jspID ) ) {
296                                            file = gamenId + "/matrixMenu" + group + ".htm";        // ④
297                                    }
298                                    gamenId = "jsp" ;                       // トリãƒ?‚­ー
299                            }
300    
301                            // 5.6.4.2 (2013/05/17) Matrixメニュー buttonRequest å»?­¢
302    //                      // 4.3.3.0 (2008/10/01) Matrixメニュー対å¿?
303    //                      //   GAMENID=XXXX&buttonRequest=true + index.jsp      �"jsp/indexXXXX.htm"
304    //                      //   GAMENID=XXXX&buttonRequest=true + multiMenu.jsp  �"jsp/menuXXXX.htm"
305    //                      //   group=YYYY&buttonRequest=true   + matrixMenu.jsp �"menu/matrixMenuYYYY.htm"
306    //                      String guiKey = request.getParameter( "GAMENID" );
307    //                      String btnReq = request.getParameter( "buttonRequest" );
308    //                      if( "true".equals( btnReq ) ) {
309    //                              if( guiKey != null ) {
310    //                                      if( "index.jsp".equals( jspID ) ) {
311    //                                              file = "jsp/index" + guiKey + ".htm";
312    //                                      }
313    //                                      else if( "multiMenu.jsp".equals( jspID ) ) {
314    //                                              file = "jsp/menu" + guiKey + ".htm";
315    //                                              gamenId = "jsp" ;       // トリãƒ?‚­ー
316    //                                      }
317    //                              }
318    //                              else {
319    //
320    //                                      String group = request.getParameter( "group" );
321    //                                      if( group  != null ) {
322    //                                              if( "matrixMenu.jsp".equals( jspID ) ) {
323    //                                                      file = "menu/matrixMenu" + group + ".htm";
324    //                                                      gamenId = "jsp" ;       // トリãƒ?‚­ー
325    //                                              }
326    //                                      }
327    //                              }
328    //                      }
329    
330    //                      int index1     = requestURI.lastIndexOf( '/',index2-1 );
331    //                      String gamenId = requestURI.substring( index1+1,index2 );
332    
333                            if( "jsp".equals( gamenId ) ) { file = saveDir + file; }
334                            else { file = saveDir + gamenId + "/" + file; }
335    
336    //                      File fl = new File( saveDir + gamenId );
337    //                      if( !fl.exists() && !fl.mkdirs() ) {
338                            File fl = new File( file ).getParentFile();
339                            if( fl != null && !fl.exists() && !fl.mkdirs() ) {
340                                    String errMsg = "æ‰?®šã?フォルãƒ?�Œ作æ?できませんでしたã€?" + fl + "]" ;
341                                    throw new RuntimeException( errMsg );
342                            }
343                    }
344    
345                    return file;
346            }
347    }