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    }