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 */
016package org.opengion.hayabusa.filter;
017
018import org.opengion.fukurou.util.StringUtil;
019import org.opengion.fukurou.util.FileUtil;
020
021import java.util.regex.Pattern ;
022import java.util.regex.Matcher ;
023import java.util.Set ;
024import java.util.HashSet ;
025import java.io.File;
026
027/**
028 * FileFilter で使用する、紙芝居用HTMLファイル作成時に内部文字列を変換するクラスです。
029 *
030 * @og.group フィルター処理
031 *
032 * @version  4.0
033 * @author   Kazuhiko Hasegawa
034 * @since    JDK5.0,
035 */
036public class FileResponseTransform {
037
038        // 5.6.4.2 (2013/05/17) JFreeChart の画像ファイル(ChartTempフォルダ) のコピー関係の固定値
039        private static final String CHART_KEY = "/ChartTemp/" ;
040        private static final int    KEY_LEN   = CHART_KEY.length();
041
042        private static final Set<String> TARGET_CHANGE_SET = new HashSet<String>();
043
044        private static final ChangeData[] data = new ChangeData[] {
045                 new ChangeData( null,"\"/[^/]*/jsp/","\"../" )                                                         // 5.5.7.2 (2012/10/09) マッチ条件を広げる
046                ,new ChangeData( null,"'/[^/]*/jsp/","'../" )                                                           // 5.5.7.2 (2012/10/09) マッチ条件を広げる
047                ,new ChangeData( null,"=\"/[^/]*/[^/]*/ChartTemp/","=\"../ChartTemp/" )         // 5.5.2.5 (2012/05/21) JfreeChart関係の画像のアドレス変換
048                ,new ChangeData( null,"='/[^/]*/[^/]*/ChartTemp/","='../ChartTemp/" )           // 5.5.2.5 (2012/05/21) JfreeChart関係の画像のアドレス変換
049                ,new ChangeData( null,"=\"/[^/]*/help/","=\"../help/" )                                         // 5.5.2.5 (2012/05/21) help関係の画像のアドレス変換
050                ,new ChangeData( null,"='/[^/]*/help/","='../help/" )                                           // 5.5.2.5 (2012/05/21) help関係の画像のアドレス変換
051                ,new ChangeData( null,"\\.jsp" ,".htm" )
052                ,new ChangeData( "forward.htm" ,"type=\"submit\"","type=\"button\"" )
053                ,new ChangeData( "forward.htm" ,"frame src=\"result","frame src=\"forward" )                                                    // 5.6.3.4 (2013/04/26) result.jsp にフレームを使うパターン(3ペイン)
054                ,new ChangeData( "reset.htm"   ,"frame src=\"result","frame src=\"forward" )                                                    // 5.6.4.2 (2013/05/17) reset.htm で、フレームを使うパターン(3ペイン)
055                ,new ChangeData( "index.htm"   ,"frame src=\"forward.htm","frame src=\"../common/dummy.html" )
056                ,new ChangeData( "index.htm"   ,"frame src=\"entry.htm"  ,"frame src=\"../common/dummy.html" )                  // 5.6.3.4 (2013/04/26) ENTRY系の特殊対応
057                ,new ChangeData( "indexRNW.htm","frame src=\"forward.htm","frame src=\"renew.htm" )
058                ,new ChangeData( "indexNW.htm" ,"frame src=\"query.htm"  ,"frame src=\"queryNW.htm" )
059                ,new ChangeData( "indexNW.htm" ,"frame src=\"entry.htm"  ,"frame src=\"../common/dummy.html" )                  // 5.6.3.4 (2013/04/26) ENTRY系の特殊対応
060                ,new ChangeData( null ,"onSubmit=\"return oneClick\\(\\);\"","onSubmit=\"return false;\"" )                             // 5.5.7.2 (2012/10/09) 変更は、すべて行う。
061                ,new ChangeData( null ,"onSubmit=\"\""                                          ,"onSubmit=\"return false;\"" )                         // 5.6.3.4 (2013/04/26) onSubmit 引数のないケースへの対応
062                ,new ChangeData( null ,"src=\"\\.\\./common/option/ajaxSubmit\\.js\\?v=[^\"]+\"","" )                                   // 5.6.3.4 (2013/04/26) ajaxSubmit.js を削除
063                // 4.3.3.0 (2008/10/01) 戻るリンクの対応
064                ,new ChangeData( "queryNW.htm" ,"=\"http://.*jsp/+?","=\"../" )
065                ,new ChangeData( "query.htm"   ,"renew\\('query.htm'","renew\\('queryNW.htm'" )                                                 // 5.6.4.2 (2013/05/17) renew('query.htm' 変換
066                 // 漢字のボタンでは、後ろにショートカット文字が入る為、前方一致で挿入する。
067        //      ,new ChangeData( "forward.htm","value=\"追加","onClick=\"location.href='insert.htm'\" value=\"追加" )
068        //      ,new ChangeData( "forward.htm","value=\"複写","onClick=\"location.href='copy.htm'\"   value=\"複写" )
069        //      ,new ChangeData( "forward.htm","value=\"変更","onClick=\"location.href='modify.htm'\" value=\"変更" )
070        //      ,new ChangeData( "forward.htm","value=\"削除","onClick=\"location.href='delete.htm'\" value=\"削除" )
071        //      ,new ChangeData( "query.htm","index.htm\\?command=RENEW"        ,"indexRNW.htm?command=RENEW" )
072        //      ,new ChangeData( null           ,"index.htm\\?command=NEW"              ,"indexNW.htm?command=NEW" )
073                ,new IndexMatrixMenuData()              // 4.3.3.0 (2008/10/01) マトリクスメニュー対応
074                ,new IndexChangeData()
075                ,new HrefChangeData()
076                ,new NoTranHrefChangeData()                     // 5.6.3.4 (2013/04/26) entry.htm に "noTransitionUrl" が存在するときの処理。
077                ,new FileDownloadChangeData()           // 5.6.4.2 (2013/05/17) fileDownload.htm 対応
078        };
079
080        /**
081         * 変換を行います。
082         * 実際には、各内部クラスのメソッドで処理を行います。
083         *
084         * @og.rev 5.6.4.2 (2013/05/17) JFreeChart の画像ファイル(ChartTempフォルダ) のコピー
085         *
086         * @param       file    対象ファイル名
087         * @param       inStr   対象データ
088         *
089         * @return      変換後データ
090         */
091        public String replace( final String file,final String inStr ) {
092                String rtnStr = inStr;
093
094                // query 画面で、登録コマンドが発行された場合の特殊処理
095                if( file.indexOf( "query.htm" ) >= 0 && inStr.indexOf( "name=\"command\" value=\"登録" ) >= 0 ) {
096                        rtnStr = inStr.replace( "forward.jsp","entry.htm" );
097                }
098
099                // 5.6.4.2 (2013/05/17) JFreeChart の画像ファイル(ChartTempフォルダ) のコピー
100                if( inStr.indexOf( "/ChartTemp/" ) >= 0 ) {
101                        chartTempFileCopy( file,inStr );
102                }
103
104                for( int i=0; i<data.length; i++ ) {
105                        rtnStr = data[i].replace( file,rtnStr );
106                }
107                return rtnStr;
108        }
109
110        /**
111         * JFreeChart の画像ファイル(ChartTempフォルダ) のコピーを行います。
112         * これは、Tomcatを停止させずに、ChartTempフォルダ を人手てコピーする予定でしたが、
113         * 万一、停止させると、ファイルが自動削除されるため、自動コピー機能を入れておきます。
114         *
115         * ここの処理は、対象データ(inStr) の文字列変換ではなく、画像ファイルを見つけて、
116         * コピーするという処理を行います。非常に特殊な処理です。
117         *
118         * @og.rev 5.6.4.2 (2013/05/17) 新規追加
119         *
120         * @param       file    対象ファイル名
121         * @param       inStr   対象データ
122         */
123        private void chartTempFileCopy( final String file,final String inStr ) {
124                // 以下、決め打ちします。本当は saveDir や、ChartTemp をパラメータから取得すべき
125                // 大前提として、fromDir = filetemp/ChartTemp/
126                //               toDir   = filetemp/DIR/ChartTemp/
127
128                int adrs = file.indexOf( "filetemp/DIR" );                      // jsp ファイルの出力先なので、DIR を含んでいます。
129                File fromDir = new File( file.substring( 0,adrs ) + "filetemp/ChartTemp/" );
130                File toDir   = new File( file.substring( 0,adrs ) + "filetemp/DIR/ChartTemp/" );
131
132                // コピー先ディレクトリが存在しなければ・・・
133                // 6.0.0.1 (2014/04/25) These nested if statements could be combined
134                if( !toDir.exists() && !toDir.mkdirs() ) {
135                        System.err.println( toDir + " の ディレクトリ作成に失敗しました。" );
136                        return ;
137                }
138
139                // 画像ファイル名を求めます。
140                int st = inStr.indexOf( CHART_KEY ) ;
141                while( st >= 0 ) {
142                        int ed = inStr.indexOf( ".png" ,st + KEY_LEN ) ;                        // 検索開始位置は、CHART_KEYの発見場所+文字数
143                        String fname = inStr.substring( st + KEY_LEN , ed + 4 );        // + 4 は、".png" の分
144
145                        FileUtil.copy( new File( fromDir,fname ) , new File( toDir,fname ) );
146
147                        st = inStr.indexOf( CHART_KEY , ed + 4 ) ;
148                }
149        }
150
151        /**
152         * 個々の変換データを管理している、データクラス
153         * このクラスは、不変クラスのため、マルチスレッドでの同時使用に対して、安全です。
154         *
155         */
156        private static class ChangeData {
157                private final String filename ;
158                private final String org ;
159                private final String rep ;
160
161                /**
162                 * デフォルトコンストラクター
163                 * サブクラス作成用に用意された、コンストラクタ。このクラス自身には不要。
164                 */
165                public ChangeData() {
166                        this( null,null,null );
167                }
168
169                /**
170                 * コンストラクター
171                 * 初期設定を行います。
172                 * 対象ファイル名は、処理を実行するかどうかの判定に使用します。
173                 * 指定の文字列が含まれているかどうかで判定します。
174                 * null の場合は、すべてのファイルを対象にします。
175                 *
176                 * @param       filename        対象ファイル名
177                 * @param       org     変換元データ
178                 * @param       rep     変換後データ
179                 */
180                public ChangeData( final String filename,final String org,final String rep ) {
181                        this.filename = filename;
182                        this.org = org;
183                        this.rep = rep;
184                }
185
186                /**
187                 * 実際に変換を行うメソッド
188                 * 内部的には、入力文字列.replaceAll( 変換元,変換後 ) メソッドを実行します。
189                 *
190                 * @param       file    対象ファイル名
191                 * @param       inStr   対象データ
192                 * @return      変換後データ
193                 */
194                public String replace( final String file,final String inStr ) {
195                        String rtnStr = inStr;
196                        if( filename == null || file.indexOf( filename ) >= 0 ) {
197                                rtnStr = inStr.replaceAll( org,rep );
198                        }
199                        return rtnStr;
200                }
201
202                /**
203                 * このオブジェクトの文字列表現
204                 * "ChangeData( " + filename + " , " + org + " , " + rep + " )" を返します。
205                 *
206                 * @return      文字列表現
207                 */
208                @Override
209                public String toString() {
210                        return "ChangeData( " + filename + " , " + org + " , " + rep + " )" ;
211                }
212        }
213
214        /**
215         * マトリクスメニュー対応のデータ置き換えクラスです。
216         * jsp/ は、先に、../ に変換済みなので、その "../" からの検索条件で判断します。
217         * multiMenu と、matrixMenu は、標準は、menu フォルダですが、場合によっては、custom フォルダに存在する
218         * 場合があるため、menu/ は検索条件に含めません。
219         * ③と④は、変換処理は無いはずなので、ロジックは記述していません。
220         *
221         *   matrixMenu対応
222         *                 URI分離          URI分離           request取出
223         *              ① gamenId="jsp"  + index.jsp       + GAMENID=XXXX  ⇒ saveDir + "jsp/indexXXXX.htm"         Matrixメニューからの画面呼出し。
224         *              ② gamenId="jsp"  + result.jsp      + GAMENID=XXXX  ⇒ saveDir + "jsp/indexXXXX.htm"         画面QUERYのヘッダーメニュー
225         *              ③ gamenId="menu" + multiMenu.jsp   + group=YYYY    ⇒ saveDir + "menu/menuYYYY.htm"         通常メニューのグループ選択
226         *              ④ gamenId="menu" + matrixMenu.jsp  + group=YYYY    ⇒ saveDir + "menu/matrixMenuYYYY.htm"   Matrixメニューのグループ選択
227         *
228         * このクラスは、不変クラスのため、マルチスレッドでの同時使用に対して、安全です。
229         *
230         * @og.rev 4.3.3.0 (2008/10/01) Matrixメニュー対応
231         * @og.rev 5.5.2.5 (2012/05/21) TopMenuTag の ONELEVEL メニューリンク対応
232         * @og.rev 5.6.4.2 (2013/05/17) 正規表現修正、判定条件変更
233         */
234        private static final class IndexMatrixMenuData extends ChangeData {
235                public String replace( final String file,final String inStr ) {
236                        String rtnStr = inStr;
237
238                        // 5.6.4.2 (2013/05/17) 正規表現修正、判定条件変更
239                        // ① gamenId="jsp"  + index.jsp       + GAMENID=XXXX  ⇒ saveDir + "jsp/indexXXXX.htm"         Matrixメニューからの画面呼出し。
240                        // ④ gamenId="menu" + matrixMenu.jsp  + group=YYYY    ⇒ saveDir + "menu/matrixMenuYYYY.htm"   Matrixメニューのグループ選択
241                        if( file.indexOf( "matrixMenu" ) >= 0 ) {
242                                rtnStr = rtnStr.replaceAll( "../index.htm\\?[^\"]*GAMENID=([^&\"]*)[^\"]*\"","../jsp/index$1.htm\"" );  // ①
243                                rtnStr = rtnStr.replaceAll( "matrixMenu.htm\\?[^\"]*group=([^&\"]*)[^\"]*\"","matrixMenu$1.htm\"" );    // ④
244                                rtnStr = rtnStr.replaceAll( "=\"../../../mr/jsp/","=\"../" );
245                        }
246                        // ② gamenId="jsp"  + result.jsp      + GAMENID=XXXX  ⇒ saveDir + "XXXX/index.htm"            画面QUERYのヘッダーメニュー
247                        else if( file.indexOf( "query" ) >= 0 ) {
248                                rtnStr = rtnStr.replaceAll( "../result.htm\\?[^\"]*GAMENID=([^&\"]*)[^\"]*\"","../jsp/index$1.htm\"" ); // ②
249                        }
250                        // ③ gamenId="menu" + multiMenu.jsp   + group=YYYY    ⇒ saveDir + "jsp/menuYYYY.htm"          通常メニューのグループ選択
251                        else if( file.indexOf( "multiMenu" ) >= 0 || file.indexOf( "menu" ) >= 0 || file.indexOf( "normalMenu" ) >= 0 ) {
252                                rtnStr = rtnStr.replaceAll( "multiMenu.htm\\?[^\"]*group=([^&\"]*)[^\"]*\"","menu$1.htm\"" );                   // ③
253                        }
254                        return rtnStr;
255                }
256
257                /**
258                 * このオブジェクトの文字列表現
259                 * "IndexMatrixMenuData()" を返します。
260                 *
261                 * @return      文字列表現
262                 */
263                @Override
264                public String toString() {
265                        return "IndexMatrixMenuData()" ;
266                }
267        }
268
269        /**
270         * index.htm のコマンド単位のファイル名の置き換えクラスです。
271         * このクラスは、不変クラスのため、マルチスレッドでの同時使用に対して、安全です。
272         *
273         */
274        private static final class IndexChangeData extends ChangeData {
275                // <a href="aaaa/index.htm?command=RENEW&GAMENID=bbbb 形式とマッチし、index.htm 部分を前方参照します。
276                private static final Pattern PTN1 = Pattern.compile( "index.htm\\?[^\"]*command=(NEW|RENEW)" );
277
278                public String replace( final String file,final String inStr ) {
279                        String rtnStr = inStr;
280        //              if( file.indexOf( "query" ) >= 0 ) {            // query の場合
281                                Matcher mch = PTN1.matcher( rtnStr );
282                                int adrs = 0;
283                                while( mch.find( adrs ) ) {
284                                        int indx = mch.start() ;
285                                        String cmd = mch.group(1);              // command=(NEW|RENEW) 部分の()内文字列
286                                        // index.htm 文字列部に、NW または RNW を追加し、indexNW.html を作成する。
287                                        if( "NEW".equalsIgnoreCase( cmd ) ) {
288                                                rtnStr = rtnStr.substring(0,indx+5) + "NW" + rtnStr.substring(indx+5) ;
289                                        }
290                                        else if( "RENEW".equalsIgnoreCase( cmd ) ) {
291                                                rtnStr = rtnStr.substring(0,indx+5) + "RNW" + rtnStr.substring(indx+5) ;
292                                        }
293                                        adrs = mch.end() ;
294                                        mch.reset( rtnStr );
295                                }
296        //              }
297                        return rtnStr;
298                }
299
300                /**
301                 * このオブジェクトの文字列表現
302                 * "IndexChangeData()" を返します。
303                 *
304                 * @return      文字列表現
305                 */
306                @Override
307                public String toString() {
308                        return "IndexChangeData()" ;
309                }
310        }
311
312        /**
313         * コマンド転送先を、onClick="location.href=XXX" で指定するように、変換します。
314         * <input type="hidden" name="hX_複写(C)" value="copy.htm" /> を見つけ、
315         * 前方参照で、複写(C) と、copy.htm を取り出します。
316         * その後、<input name="command" value="複写(C)" という文字列をキーに、
317         * <input name="command" onClick="location.href='copy.htm'" value="複写(C)" という
318         * 文字列に置き換えます。
319         * これにより、ボタンを押したときに、ボタンごとに異なる画面に遷移します。
320         * 前提条件として、下記の項目を満たしておく必要がある。
321         *   ・form には、onSubmit="return false;" を記述し、フォームを無効化しておく。
322         *   ・input タグの type="submit" を、type="button" にしておく。(ボタンイベント)
323         *   ・query.htm 以外のファイルのみ適用。location.href では、フレームのtarget指定
324         *     まで行っていない。
325         *   ・上と同意で、query.htm の登録時処理は、別に行う。
326         *
327         * @og.rev 5.5.2.5 (2012/05/21) update.jsp に出力されるファイルを、コマンド名.htm に出力するように機能追加
328         * @og.rev 5.6.4.2 (2013/05/17) 3ペイン、エントリなど、特殊な画面にフラグを付けます。(TARGET_CHANGE_SET)
329         */
330        private static final class HrefChangeData extends ChangeData {
331                private static final String PTN1 = "<input type=\"hidden\" name=\"hX_([^\"]*)\" value=\"([^\"]*.htm)" ;
332                private static final Pattern ptnObj1 = Pattern.compile( PTN1 );
333
334                // 5.5.7.2 (2012/10/09) 定数名の変更
335                private static final String ORG  = "<input name=\"command\"" ;
336                private static final String SELF = "<input name=\"command\" onClick=\"location.href='" ;
337                private static final String PRNT = "<input name=\"command\" onClick=\"parent.location.href='" ;
338                private static final String TOP  = "<input name=\"command\" onClick=\"top.location.href='" ;
339
340                // 5.5.7.2 (2012/10/09) formのtargetを取得。location.href に利用する。
341                private static final String PTN2 = "<form .*target=\"([^\"]*)\"" ;
342                private static final Pattern ptnObj2 = Pattern.compile( PTN2 );
343
344                /**
345                 * コマンド転送先を、onClick="location.href=XXX" で指定するように、変換します。
346                 * <input type="hidden" name="hX_複写(C)" value="copy.htm" /> を見つけ、
347                 * 前方参照で、複写(C) と、copy.htm を取り出します。
348                 * その後、<input name="command" value="複写(C)" という文字列をキーに、
349                 * <input name="command" onClick="location.href='copy.htm'" value="複写(C)" という
350                 * 文字列に置き換えます。
351                 *
352                 * @og.rev 5.5.2.5 (2012/05/21) update.jsp に出力されるファイルを、コマンド名.htm に出力するように機能追加
353                 * @og.rev 5.5.7.2 (2012/10/09) 定数名の変更。formのtargetを加味した、location.href を作成する。
354                 * @og.rev 5.6.4.2 (2013/05/17) 3ペイン、エントリなど、特殊な画面にフラグを付けます。(TARGET_CHANGE_SET)
355                 *
356                 * @param       file    対象ファイル名
357                 * @param       inStr   対象データ
358                 * @return      変換後データ
359                 */
360                public String replace( final String file,final String inStr ) {
361                        String rtnStr = inStr;
362                        if( file.indexOf( "query.htm" ) < 0 ) {         // query.htm 以外の場合
363                                // 5.5.7.2 (2012/10/09) formのtargetを加味した、location.href を作成する。
364                                Matcher mch2 = ptnObj2.matcher( rtnStr );
365                                String ptnHref = SELF;                  // 標準は、location.href
366                                if( mch2.find() ) {
367                                        // 5.6.4.2 (2013/05/17) 3ペイン、エントリなど、特殊な画面にフラグを付けます。(TARGET_CHANGE_SET)
368                                        int indx = file.lastIndexOf( '/' );
369                                        String fileKey = file.substring( 0,indx );
370
371                                        String frmTgt = mch2.group(1);
372                                        if( "CONTENTS".equals( frmTgt ) )  { ptnHref = PRNT; }
373                                        else if( "_top".equals( frmTgt ) ) { ptnHref = TOP;  }
374                                        else if( !"RESULT".equals( frmTgt ) && frmTgt != null ) {
375                                                ptnHref = "<input name=\"command\" onClick=\"parent." + frmTgt + ".location.href='" ;
376                                                // 5.6.4.2 (2013/05/17) ある画面で、特殊なターゲット(INPUT,BUTTOMなど)を使用している場合に記憶
377                                                TARGET_CHANGE_SET.add( fileKey );               // 別のファイルを処理するときに参照する。
378                                        }
379                                        else {
380                                                // 5.6.4.2 (2013/05/17) ある画面で、特殊なターゲット(INPUT,BUTTOMなど)を使用している場合のチェック
381                                                if( TARGET_CHANGE_SET.contains( fileKey ) ) {
382                                                        ptnHref = PRNT ;
383                                                }
384                                        }
385                                }
386
387                                Matcher mch = ptnObj1.matcher( rtnStr );
388                                int adrs = 0;
389                                while( mch.find( adrs ) ) {
390                                        String cmd = mch.group(1);
391                                        if( !cmd.endsWith( "CMD" ) ) {
392                                                String val = mch.group(2);
393                                                String str1 = ORG + " value=\"" + cmd ;
394                                                String str2 ;
395
396                                                if( val != null && val.startsWith( "../" ) ) {
397                                                        str2 = PRNT + val + "'\" value=\"" + cmd ;
398                                                }
399                                                // 5.5.2.5 (2012/05/21) update.jsp に出力されるファイルを、コマンド名.htm に出力するように機能追加
400                                                else if( val != null && val.startsWith( "update" ) ) {
401                                                        str2 = ptnHref + cmd + ".htm'\" value=\"" + cmd ;
402                                                }
403                                                else {
404                                                        str2 = ptnHref + val + "'\" value=\"" + cmd ;
405                                                }
406                                                rtnStr = rtnStr.replace( str1,str2 );
407                                        }
408                                        adrs = mch.end();
409                                        mch.reset( rtnStr );
410                                }
411                        }
412                        return rtnStr;
413                }
414
415                /**
416                 * このオブジェクトの文字列表現
417                 * "HrefChangeData()" を返します。
418                 *
419                 * @return      文字列表現
420                 */
421                @Override
422                public String toString() {
423                        return "HrefChangeData()" ;
424                }
425        }
426
427        /**
428         * 雛形自動作成 で、useAjaxSubmit="true" の対策
429         *
430         * update.jsp で、useAjaxSubmit="true" の場合、entry.htm は、update.jsp の 
431         * JavaScriptでforward されるため、雛形には、HTMLの結果は出力されません。
432         * (result.jsp に出力されます。)
433         * そこで、雛形作成時には、entry.htm にJavaScriptを入れて、forward させます。
434         * このクラスは、不変クラスのため、マルチスレッドでの同時使用に対して、安全です。
435         * 挿入するのは、BODYタグの最後です。BODYタグがなければ、最後に追加します。
436         *
437         * @og.rev 5.6.3.4 (2013/04/26) entry.htm に "noTransitionUrl" が存在するときの処理。
438         */
439        private static final class NoTranHrefChangeData extends ChangeData {
440                private static final String BODY_END   = "</body>" ;
441                private static final String APPEND_JS  = "<script type=\"text/javascript\" src=\"../common/option/noTranHref.js\" ><!-- --></script>" ;
442
443                public String replace( final String file,final String inStr ) {
444                        String rtnStr = inStr;
445                        // entry.jsp で、かつ noTransitionUrl 文字列を含む場合のみ
446                        if( file.indexOf( "entry" ) >= 0 && inStr.indexOf( "noTransitionUrl" ) >= 0 ) {
447                                int adrs = inStr.indexOf( BODY_END );
448                                if( adrs > 0 ) {                // </body> タグが存在した場合は、その直前に挿入する。
449                                        rtnStr = inStr.substring( 0,adrs ) + APPEND_JS + inStr.substring( adrs ) ;
450                                }
451                                else {                                  // 存在しない場合は、最後に挿入する。
452                                        rtnStr = inStr + APPEND_JS ;
453                                }
454                        }
455                        return rtnStr;
456                }
457
458                /**
459                 * このオブジェクトの文字列表現
460                 * "NoTranHrefChangeData()" を返します。
461                 *
462                 * @return      文字列表現
463                 */
464                @Override
465                public String toString() {
466                        return "NoTranHrefChangeData()" ;
467                }
468        }
469
470        /**
471         * 雛形自動作成 で、fileDownload の日本語名対応
472         *
473         * 標準的な、fileDownload 処理では、../common/fileDownload.jsp?・・・・GAMENID=XXXX&filename=YYYY" と
474         * なっており、filename 部分は、日本語にも対応できるように urlEncode されています。
475         * これを、元に戻さないとうまくダウンロードできませんでした。
476         *
477         * ※ 参考情報
478         *  1.urlEncode のままで、ファイル名を取得する場合は、下記の標準系で対応可能です。
479         *              ,new ChangeData( null ,"../common/fileDownload.htm\\?[^\"]*filename=([^&\"]*)[^\"]*\"","$1\"" )
480         *  2.ファイル名を、fileDownload.xls 固定にする場合は、下記の標準系で対応可能です。
481         *              ,new ChangeData( null ,"../common/fileDownload.htm\\?[^\"]*\"","fileDownload.xls\"" )
482         *
483         * @og.rev 5.6.4.2 (2013/05/17) 新規追加
484         */
485        private static final class FileDownloadChangeData extends ChangeData {
486                private static final String PTN1 = "../common/fileDownload.htm\\?[^\"]*filename=([^&\"]*)[^\"]*\"" ;
487                private static final Pattern ptnObj1 = Pattern.compile( PTN1 );
488
489                public String replace( final String file,final String inStr ) {
490                        String rtnStr = inStr;
491                        // entry.jsp で、かつ noTransitionUrl 文字列を含む場合のみ
492                        if( rtnStr.indexOf( "../common/fileDownload.htm" ) >= 0 ) {
493                                Matcher mch = ptnObj1.matcher( rtnStr );
494                                int adrs = 0;
495                                while( mch.find( adrs ) ) {
496                                        String fname = mch.group(1);
497                                        fname = StringUtil.urlDecode( fname );          // デコードしています。
498
499                                        int indx = mch.start() ;
500                                        adrs = mch.end();
501                                        rtnStr = rtnStr.substring( 0,indx ) + fname + "\"" + rtnStr.substring( adrs ) ;
502
503                                        mch.reset( rtnStr );
504                                }
505                        }
506                        return rtnStr;
507                }
508
509                /**
510                 * このオブジェクトの文字列表現
511                 * "FileDownloadChangeData()" を返します。
512                 *
513                 * @return      文字列表現
514                 */
515                @Override
516                public String toString() {
517                        return "FileDownloadChangeData()" ;
518                }
519        }
520}