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.hayabusa.common.HybsSystem; // 6.9.9.2 (2018/09/18) 019import org.opengion.fukurou.util.StringUtil; 020import org.opengion.fukurou.util.FileUtil; 021 022import java.util.regex.Pattern ; 023import java.util.regex.Matcher ; 024import java.util.Set ; 025import java.util.HashSet ; 026import java.io.File; 027 028/** 029 * FileFilter で使用する、紙芝居用HTMLファイル作成時に内部文字列を変換するクラスです。 030 * 031 * @og.group フィルター処理 032 * 033 * @version 4.0 034 * @author Kazuhiko Hasegawa 035 * @since JDK5.0, 036 */ 037public class FileResponseTransform { 038 039 // 5.6.4.2 (2013/05/17) JFreeChart の画像ファイル(ChartTempフォルダ) のコピー関係の固定値 040 private static final String CHART_KEY = "/ChartTemp/" ; 041 private static final int KEY_LEN = CHART_KEY.length(); 042 043 private static final Set<String> TARGET_CHANGE_SET = new HashSet<>(); 044 045 private static final ChangeData[] CHG_DATA = new ChangeData[] { // 6.4.1.1 (2016/01/16) data → CHG_DATA refactoring 046 new ChangeData( null , "\"/[^/]*/jsp/" ,"\"../" ) // 5.5.7.2 (2012/10/09) マッチ条件を広げる 047 ,new ChangeData( null , "'/[^/]*/jsp/" ,"'../" ) // 5.5.7.2 (2012/10/09) マッチ条件を広げる 048 ,new ChangeData( null , "\\(/[^/]*/jsp/" ,"(../" ) // 6.4.3.2 (2016/02/19) マッチ条件を広げる 049 ,new ChangeData( null , "=\"/[^/]*/[^/]*/ChartTemp/","=\"../ChartTemp/" ) // 5.5.2.5 (2012/05/21) JfreeChart関係の画像のアドレス変換 050 ,new ChangeData( null , "='/[^/]*/[^/]*/ChartTemp/" ,"='../ChartTemp/" ) // 5.5.2.5 (2012/05/21) JfreeChart関係の画像のアドレス変換 051 ,new ChangeData( null , "=\"/[^/]*/help/" ,"=\"../help/" ) // 5.5.2.5 (2012/05/21) help関係の画像のアドレス変換 052 ,new ChangeData( null , "='/[^/]*/help/" ,"='../help/" ) // 5.5.2.5 (2012/05/21) help関係の画像のアドレス変換 053 ,new ChangeData( null , "\\.jsp" ,".htm" ) 054 ,new ChangeData( "query.htm" , "action=\"result" ,"action=\"forward" ) // 6.2.5.0 (2015/06/05) GMIS V6 対応(3ペイン対応) 055 ,new ChangeData( "forward.htm" , "frame src=\"result" ,"frame src=\"forward" ) // 5.6.3.4 (2013/04/26) forward.htm にフレームを使うパターン(3ペイン) 056 ,new ChangeData( "reset.htm" , "frame src=\"result" ,"frame src=\"forward" ) // 5.6.4.2 (2013/05/17) reset.htm で、フレームを使うパターン(3ペイン) 057 ,new ChangeData( "index.htm" , "frame src=\"forward.htm" ,"frame src=\"../common/dummy.html" ) 058 ,new ChangeData( "index.htm" , "frame src=\"entry.htm" ,"frame src=\"../common/dummy.html" ) // 5.6.3.4 (2013/04/26) ENTRY系の特殊対応 059 ,new ChangeData( "indexRNW.htm" , "frame src=\"forward.htm" ,"frame src=\"renew.htm" ) 060 ,new ChangeData( "indexNW.htm" , "frame src=\"query.htm" ,"frame src=\"queryNW.htm" ) 061 ,new ChangeData( "indexNW.htm" , "frame src=\"entry.htm" ,"frame src=\"../common/dummy.html" ) // 5.6.3.4 (2013/04/26) ENTRY系の特殊対応 062 ,new ChangeData( "entry" , "<input[^>]*history.back[^>]*>" ,"" ) // 6.3.8.0 (2015/09/11) hiistory.back() のタグ削除 の対象を、entry を含むに変更 063 ,new ChangeData( null , "onSubmit=\"return oneClick\\(\\);\"","onSubmit=\"return false;\"" ) // 5.5.7.2 (2012/10/09) 変更は、すべて行う。 064 ,new ChangeData( null , "onSubmit=\"\"" ,"onSubmit=\"return false;\"" ) // 5.6.3.4 (2013/04/26) onSubmit 引数のないケースへの対応 065 ,new ChangeData( null , "src=\"\\.\\./common/option/ajaxSubmit\\.js\\?v=[^\"]+\"","" ) // 5.6.3.4 (2013/04/26) ajaxSubmit.js を削除 066 // 4.3.3.0 (2008/10/01) 戻るリンクの対応 067 ,new ChangeData( "queryNW.htm" ,"=\"http://.*jsp/+?" ,"=\"../" ) 068// ,new ChangeData( "queryNW.htm" ,"\"query.htm?" ,"\"querNWy.htm?" ) // 6.4.2.1 (2016/02/05) クリアボタンのとび先 069 ,new ChangeData( "queryNW.htm" ,"\"query.htm?" ,"\"queryNW.htm?" ) // 6.9.3.1 (2018/04/02) クリアボタンのとび先(綴り間違い) 070 ,new ChangeData( "query.htm" ,"renew\\('query.htm'" ,"renew\\('queryNW.htm'" ) // 5.6.4.2 (2013/05/17) renew('query.htm' 変換 071 // 漢字のボタンでは、後ろにショートカット文字が入る為、前方一致で挿入する。 072 // ,new ChangeData( "forward.htm","value=\"追加","onClick=\"location.href='insert.htm'\" value=\"追加" ) 073 // ,new ChangeData( "forward.htm","value=\"複写","onClick=\"location.href='copy.htm'\" value=\"複写" ) 074 // ,new ChangeData( "forward.htm","value=\"変更","onClick=\"location.href='modify.htm'\" value=\"変更" ) 075 // ,new ChangeData( "forward.htm","value=\"削除","onClick=\"location.href='delete.htm'\" value=\"削除" ) 076 // ,new ChangeData( "query.htm","index.htm\\?command=RENEW" ,"indexRNW.htm?command=RENEW" ) 077 // ,new ChangeData( null ,"index.htm\\?command=NEW" ,"indexNW.htm?command=NEW" ) 078 ,new IndexMatrixMenuData() // 4.3.3.0 (2008/10/01) マトリクスメニュー対応 079 ,new IndexChangeData() 080 ,new HrefChangeData() 081 ,new NoTranHrefChangeData() // 5.6.3.4 (2013/04/26) entry.htm に "noTransitionUrl" が存在するときの処理。 082 ,new FileDownloadChangeData() // 5.6.4.2 (2013/05/17) fileDownload.htm 対応 083 ,new ChangeData( "multiMenu.htm" , "\\.\\./common/gamen", "../") // 6.9.9.2 (2018/09/18) oota tmp add 01_「menu_リンク先微調整_管谷」対応 084 ,new ChangeData( null, "\\.\\./common/reportView.htm", "reportView.htm") // 6.9.9.2 (2018/09/18) oota tmp 02_「SAL1021_出荷_帳票リンク_新沼」対応 085 // 6.9.9.2 (2018/09/18) oota tmp POPUP対応(href指定あり) 03_「POPUP全般_index.htm作成されない_管谷」対応 086 ,new ChangeData( null, "(ogPopup\\( '\\.\\./.*?/)(index|query).htm", "$1$2NW.htm") 087 // 6.9.9.2 (2018/09/18) oota tmp POPUP対応(href指定なし) indexNW.htmを付与 03_「POPUP全般_index.htm作成されない_管谷」対応 088 ,new ChangeData( null, "(ogPopup\\( '\\.\\./.*?/)'", "$1indexNW.htm'") 089 // 6.9.9.2 (2018/09/18) oota tmp submitタグでgamenIdを指定して、別画面に遷移時。 04_「FMA0103_ドキュメント登録_追加ボタンが動作しない_原野」対応 090 ,new ChangeData( null, "(parent.location.href='\\.\\./.*?/)(index|query).htm", "$1$2NW.htm") 091 ,new QuerySubmitChange() // 6.9.9.2 (2018/09/18) oota tmp add 09_「DIE0005_金型保守_チェック処理ボタン動かない_北林」対応 092 }; 093 094 /** 095 * デフォルトコンストラクター 096 * 097 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor. 098 */ 099 public FileResponseTransform() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 100 101 /** 102 * 変換を行います。 103 * 実際には、各内部クラスのメソッドで処理を行います。 104 * 105 * @og.rev 5.6.4.2 (2013/05/17) JFreeChart の画像ファイル(ChartTempフォルダ) のコピー 106 * 107 * @param file 対象ファイル名 108 * @param inStr 対象データ 109 * 110 * @return 変換後データ 111 */ 112 public String replace( final String file,final String inStr ) { 113 String rtnStr = inStr; 114 115 // query 画面で、登録コマンドが発行された場合の特殊処理 116 if( file.indexOf( "query.htm" ) >= 0 && inStr.indexOf( "name=\"command\" value=\"登録" ) >= 0 ) { 117 rtnStr = inStr.replace( "forward.jsp","entry.htm" ); 118 } 119 120 // 5.6.4.2 (2013/05/17) JFreeChart の画像ファイル(ChartTempフォルダ) のコピー 121 if( inStr.indexOf( "/ChartTemp/" ) >= 0 ) { 122 chartTempFileCopy( file,inStr ); 123 } 124 125 for( int i=0; i<CHG_DATA.length; i++ ) { 126 rtnStr = CHG_DATA[i].replace( file,rtnStr ); 127 } 128 return rtnStr; 129 } 130 131 /** 132 * JFreeChart の画像ファイル(ChartTempフォルダ) のコピーを行います。 133 * これは、Tomcatを停止させずに、ChartTempフォルダ を人手てコピーする予定でしたが、 134 * 万一、停止させると、ファイルが自動削除されるため、自動コピー機能を入れておきます。 135 * 136 * ここの処理は、対象データ(inStr) の文字列変換ではなく、画像ファイルを見つけて、 137 * コピーするという処理を行います。非常に特殊な処理です。 138 * 139 * @og.rev 5.6.4.2 (2013/05/17) 新規追加 140 * 141 * @param file 対象ファイル名 142 * @param inStr 対象データ 143 */ 144 private void chartTempFileCopy( final String file,final String inStr ) { 145 // 以下、決め打ちします。本当は saveDir や、ChartTemp をパラメータから取得すべき 146 // 大前提として、fromDir = filetemp/ChartTemp/ 147 // toDir = filetemp/DIR/ChartTemp/ 148 149 final int adrs = file.indexOf( "filetemp/DIR" ); // jsp ファイルの出力先なので、DIR を含んでいます。 150 final File toDir = new File( file.substring( 0,adrs ) + "filetemp/DIR/ChartTemp/" ); 151 152 // コピー先ディレクトリが存在しなければ・・・ 153 // 6.0.0.1 (2014/04/25) These nested if statements could be combined 154 if( !toDir.exists() && !toDir.mkdirs() ) { 155 System.err.println( toDir + " の ディレクトリ作成に失敗しました。" ); 156 return ; 157 } 158 159 // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid declaring a variable if it is unreferenced before a possible exit point. 160 final File fromDir = new File( file.substring( 0,adrs ) + "filetemp/ChartTemp/" ); 161 // 画像ファイル名を求めます。 162 int st = inStr.indexOf( CHART_KEY ) ; 163 while( st >= 0 ) { 164 final int ed = inStr.indexOf( ".png" ,st + KEY_LEN ) ; // 検索開始位置は、CHART_KEYの発見場所+文字数 165 final String fname = inStr.substring( st + KEY_LEN , ed + 4 ); // + 4 は、".png" の分 166 167 FileUtil.copy( new File( fromDir,fname ) , new File( toDir,fname ) ); 168 169 st = inStr.indexOf( CHART_KEY , ed + 4 ) ; 170 } 171 } 172 173 /** 174 * 個々の変換データを管理している、データクラス 175 * このクラスは、不変クラスのため、マルチスレッドでの同時使用に対して、安全です。 176 * 177 * ※ このクラスは継承されるため、final化しません。 178 */ 179 private static class ChangeData { 180 private final String filename ; 181 private final String org ; 182 private final String rep ; 183 184 /** 185 * デフォルトコンストラクター 186 * サブクラス作成用に用意された、コンストラクタ。このクラス自身には不要。 187 */ 188 public ChangeData() { 189 this( null,null,null ); 190 } 191 192 /** 193 * コンストラクター 194 * 初期設定を行います。 195 * 対象ファイル名は、処理を実行するかどうかの判定に使用します。 196 * 指定の文字列が含まれているかどうかで判定します。 197 * null の場合は、すべてのファイルを対象にします。 198 * 199 * @param filename 対象ファイル名 200 * @param org 変換元データ 201 * @param rep 変換後データ 202 */ 203 public ChangeData( final String filename,final String org,final String rep ) { 204 this.filename = filename; 205 this.org = org; 206 this.rep = rep; 207 } 208 209 /** 210 * 実際に変換を行うメソッド 211 * 内部的には、入力文字列.replaceAll( 変換元,変換後 ) メソッドを実行します。 212 * 213 * @param file 対象ファイル名 214 * @param inStr 対象データ 215 * @return 変換後データ 216 */ 217 public String replace( final String file,final String inStr ) { 218 219 String rtnStr = inStr; 220 if( filename == null || file.indexOf( filename ) >= 0 ) { 221 rtnStr = inStr.replaceAll( org,rep ); 222 } 223 return rtnStr; 224 } 225 226 /** 227 * このオブジェクトの文字列表現 228 * "ChangeData( " + filename + " , " + org + " , " + rep + " )" を返します。 229 * 230 * @return 文字列表現 231 * @og.rtnNotNull 232 */ 233 @Override 234 public String toString() { 235 return "ChangeData( " + filename + " , " + org + " , " + rep + " )" ; 236 } 237 } 238 239 /** 240 * マトリクスメニュー対応のデータ置き換えクラスです。 241 * jsp/ は、先に、../ に変換済みなので、その "../" からの検索条件で判断します。 242 * multiMenu と、matrixMenu は、標準は、menu フォルダですが、場合によっては、custom フォルダに存在する 243 * 場合があるため、menu/ は検索条件に含めません。 244 * ③と④は、変換処理は無いはずなので、ロジックは記述していません。 245 * 246 * matrixMenu対応 247 * URI分離 URI分離 request取出 248 * ① gamenId="jsp" + index.jsp + GAMENID=XXXX ⇒ saveDir + "jsp/indexXXXX.htm" Matrixメニューからの画面呼出し。 249 * ② gamenId="jsp" + result.jsp + GAMENID=XXXX ⇒ saveDir + "jsp/indexXXXX.htm" 画面QUERYのヘッダーメニュー 250 * ③ gamenId="menu" + multiMenu.jsp + group=YYYY ⇒ saveDir + "menu/menuYYYY.htm" 通常メニューのグループ選択 251 * ④ gamenId="menu" + matrixMenu.jsp + group=YYYY ⇒ saveDir + "menu/matrixMenuYYYY.htm" Matrixメニューのグループ選択 252 * 253 * このクラスは、不変クラスのため、マルチスレッドでの同時使用に対して、安全です。 254 * 255 * @og.rev 4.3.3.0 (2008/10/01) Matrixメニュー対応 256 * @og.rev 5.5.2.5 (2012/05/21) TopMenuTag の ONELEVEL メニューリンク対応 257 * @og.rev 5.6.4.2 (2013/05/17) 正規表現修正、判定条件変更 258 * @og.rev 6.3.8.4 (2015/10/09) セーブフォルダを、URIではなく、画面IDから取得する。 259 * @og.rev 6.4.3.2 (2016/02/19) matrixMenu の、../画面ID/index.htm の場合の対応 260 */ 261 private static final class IndexMatrixMenuData extends ChangeData { 262 /** 263 * 実際に変換を行うメソッド。 264 * 265 * @param file 対象ファイル名 266 * @param inStr 対象データ 267 * @return 変換後データ 268 */ 269 @Override 270 public String replace( final String file,final String inStr ) { 271 String rtnStr = inStr; 272 273 // 5.6.4.2 (2013/05/17) 正規表現修正、判定条件変更 274 // ① gamenId="jsp" + index.jsp + GAMENID=XXXX ⇒ saveDir + "jsp/indexXXXX.htm" Matrixメニューからの画面呼出し。 275 // ④ gamenId="menu" + matrixMenu.jsp + group=YYYY ⇒ saveDir + "menu/matrixMenuYYYY.htm" Matrixメニューのグループ選択 276 if( file.indexOf( "matrixMenu" ) >= 0 ) { 277 // 6.4.3.2 (2016/02/19) ../画面ID/index.htm の場合の対応 278 // 6.4.3.2 (2016/02/19) 従来の../index.htm では、/ がひとつなので、注意。先頭の ".. にしておかないと、前方のタグまで食ってしまう。 279 rtnStr = rtnStr.replaceAll( "\"../[^/]*[/]*index.htm\\?[^\"]*GAMENID=([^&\"]*)[^\"]*\"","\"../jsp/index$1.htm\"" ); // ① 280 rtnStr = rtnStr.replaceAll( "matrixMenu.htm\\?[^\"]*group=([^&\"]*)[^\"]*\"","matrixMenu$1.htm\"" ); // ④ 281 rtnStr = rtnStr.replaceAll( "=\"../../../mr/jsp/","=\"../" ); 282 } 283 // 6.3.8.4 (2015/10/09) セーブフォルダを、URIではなく、画面IDから取得する。 284 // ① のケースの、jsp/indexXXXX.htm ファイルの内容(frame)のフォルダ名を画面IDに変更 285 else if( file.indexOf( "jsp/index" ) >= 0 ) { 286 rtnStr = rtnStr.replaceAll( "frame src=\"../[^\"]*GAMENID=([^&\"]*)[^\"]*\"","frame src=\"../$1/index.htm\"" ); // ① 287 } 288 // ② gamenId="jsp" + result.jsp + GAMENID=XXXX ⇒ saveDir + "XXXX/index.htm" 画面QUERYのヘッダーメニュー 289 else if( file.indexOf( "query" ) >= 0 ) { 290 rtnStr = rtnStr.replaceAll( "../result.htm\\?[^\"]*GAMENID=([^&\"]*)[^\"]*\"","../jsp/index$1.htm\"" ); // ② 291 } 292 // ③ gamenId="menu" + multiMenu.jsp + group=YYYY ⇒ saveDir + "jsp/menuYYYY.htm" 通常メニューのグループ選択 293 else if( file.indexOf( "multiMenu" ) >= 0 || file.indexOf( "menu" ) >= 0 || file.indexOf( "normalMenu" ) >= 0 ) { 294 rtnStr = rtnStr.replaceAll( "multiMenu.htm\\?[^\"]*group=([^&\"]*)[^\"]*\"","menu$1.htm\"" ); // ③ 295 } 296 return rtnStr; 297 } 298 299 /** 300 * このオブジェクトの文字列表現 301 * "IndexMatrixMenuData()" を返します。 302 * 303 * @return 文字列表現 304 * @og.rtnNotNull 305 */ 306 @Override 307 public String toString() { 308 return "IndexMatrixMenuData()" ; 309 } 310 } 311 312 /** 313 * index.htm のコマンド単位のファイル名の置き換えクラスです。 314 * このクラスは、不変クラスのため、マルチスレッドでの同時使用に対して、安全です。 315 * 316 */ 317 private static final class IndexChangeData extends ChangeData { 318 // <a href="aaaa/index.htm?command=RENEW&GAMENID=bbbb 形式とマッチし、index.htm 部分を前方参照します。 319 private static final Pattern PTN1 = Pattern.compile( "index.htm\\?[^\"]*command=(NEW|RENEW)" ); 320 321 /** 322 * 実際に変換を行うメソッド。 323 * 324 * @param file 対象ファイル名 325 * @param inStr 対象データ 326 * @return 変換後データ 327 */ 328 @Override 329 public String replace( final String file,final String inStr ) { 330 String rtnStr = inStr; 331 // if( file.indexOf( "query" ) >= 0 ) { // query の場合 332 final Matcher mch = PTN1.matcher( rtnStr ); 333 int adrs = 0; 334 while( mch.find( adrs ) ) { 335 final int indx = mch.start() ; 336 final String cmd = mch.group(1); // command=(NEW|RENEW) 部分の()内文字列 337 // index.htm 文字列部に、NW または RNW を追加し、indexNW.html を作成する。 338 if( "NEW".equalsIgnoreCase( cmd ) ) { 339 rtnStr = rtnStr.substring(0,indx+5) + "NW" + rtnStr.substring(indx+5) ; 340 } 341 else if( "RENEW".equalsIgnoreCase( cmd ) ) { 342 rtnStr = rtnStr.substring(0,indx+5) + "RNW" + rtnStr.substring(indx+5) ; 343 } 344 adrs = mch.end() ; 345 mch.reset( rtnStr ); 346 } 347 // } 348 return rtnStr; 349 } 350 351 /** 352 * このオブジェクトの文字列表現 353 * "IndexChangeData()" を返します。 354 * 355 * @return 文字列表現 356 * @og.rtnNotNull 357 */ 358 @Override 359 public String toString() { 360 return "IndexChangeData()" ; 361 } 362 } 363 364 /** 365 * コマンド転送先を、onClick="location.href=XXX" で指定するように、変換します。 366 * <input type="hidden" name="hX_複写(C)" value="copy.htm" > を見つけ、 367 * 前方参照で、複写(C) と、copy.htm を取り出します。 368 * その後、<input name="command" value="複写(C)" という文字列をキーに、 369 * <input name="command" onClick="location.href='copy.htm'" value="複写(C)" という 370 * 文字列に置き換えます。 371 * これにより、ボタンを押したときに、ボタンごとに異なる画面に遷移します。 372 * 前提条件として、下記の項目を満たしておく必要がある。 373 * ・form には、onSubmit="return false;" を記述し、フォームを無効化しておく。 374 * ・input タグの type="submit" を、type="button" にしておく。(ボタンイベント) 375 * ・query.htm 以外のファイルのみ適用。location.href では、フレームのtarget指定 376 * まで行っていない。 377 * ・上と同意で、query.htm の登録時処理は、別に行う。 378 * 379 * @og.rev 5.5.2.5 (2012/05/21) update.jsp に出力されるファイルを、コマンド名.htm に出力するように機能追加 380 * @og.rev 5.6.4.2 (2013/05/17) 3ペイン、エントリなど、特殊な画面にフラグを付けます。(TARGET_CHANGE_SET) 381 * @og.rev 6.2.5.0 (2015/06/05) GMIS V6 対応(location.href時に、type="submit" を type="button" に変更) 382 */ 383 private static final class HrefChangeData extends ChangeData { 384 private static final String PTN1 = "<input type=\"hidden\" name=\"hX_([^\"]*)\" value=\"([^\"]*.htm)" ; 385 private static final Pattern PTN_OBJ1 = Pattern.compile( PTN1 ); // 6.4.1.1 (2016/01/16) ptnObj1 → PTN_OBJ1 refactoring 386 387 // 5.5.7.2 (2012/10/09) 定数名の変更 388 private static final String ORG = "<input name=\"command\"" ; 389 private static final String SELF = "<input name=\"command\" onClick=\"location.href='" ; 390 private static final String PRNT = "<input name=\"command\" onClick=\"parent.location.href='" ; 391 private static final String TOP = "<input name=\"command\" onClick=\"top.location.href='" ; 392 393 // 5.5.7.2 (2012/10/09) formのtargetを取得。location.href に利用する。 394 private static final String PTN2 = "<form .*target=\"([^\"]*)\"" ; 395 private static final Pattern PTN_OBJ2 = Pattern.compile( PTN2 ); // 6.4.1.1 (2016/01/16) ptnObj2 → PTN_OBJ2 refactoring 396 397 // 6.2.5.0 (2015/06/05) GMIS V6 対応(location.href時に、type="submit" を type="button" に変更) 398 private static final String LOC_HREF = "location.href" ; 399 private static final String TP_SUBMIT = "type=\"submit\"" ; 400 private static final String TP_BUTTON = "type=\"button\"" ; 401 402 /** 403 * コマンド転送先を、onClick="location.href=XXX" で指定するように、変換します。 404 * <input type="hidden" name="hX_複写(C)" value="copy.htm" > を見つけ、 405 * 前方参照で、複写(C) と、copy.htm を取り出します。 406 * その後、<input name="command" value="複写(C)" という文字列をキーに、 407 * <input name="command" onClick="location.href='copy.htm'" value="複写(C)" という 408 * 文字列に置き換えます。 409 * 410 * @og.rev 5.5.2.5 (2012/05/21) update.jsp に出力されるファイルを、コマンド名.htm に出力するように機能追加 411 * @og.rev 5.5.7.2 (2012/10/09) 定数名の変更。formのtargetを加味した、location.href を作成する。 412 * @og.rev 5.6.4.2 (2013/05/17) 3ペイン、エントリなど、特殊な画面にフラグを付けます。(TARGET_CHANGE_SET) 413 * @og.rev 6.2.5.0 (2015/06/05) query*** 以外 414 * @og.rev 6.3.8.0 (2015/09/11) idxEnd = -1 の場合、無限ループになる。(javadoc上では -1 のハズ) 415 * @og.rev 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"/>" 止めを、">" に変更します)。 416 * 417 * @param file 対象ファイル名 418 * @param inStr 対象データ 419 * @return 変換後データ 420 */ 421 @Override 422 public String replace( final String file,final String inStr ) { 423 String rtnStr = inStr; 424 // 6.2.5.0 (2015/06/05) query.htm , queryNW.htm , query1.htm 以外 425 if( file.indexOf( "query" ) < 0 ) { // 6.2.5.0 (2015/06/05) query*** 以外 426 // 5.5.7.2 (2012/10/09) formのtargetを加味した、location.href を作成する。 427 final Matcher mch2 = PTN_OBJ2.matcher( rtnStr ); 428 String ptnHref = SELF; // 標準は、location.href 429 if( mch2.find() ) { 430 // 5.6.4.2 (2013/05/17) 3ペイン、エントリなど、特殊な画面にフラグを付けます。(TARGET_CHANGE_SET) 431 final int indx = file.lastIndexOf( '/' ); 432 final String fileKey = file.substring( 0,indx ); 433 434 final String frmTgt = mch2.group(1); 435 if( "CONTENTS".equals( frmTgt ) ) { ptnHref = PRNT; } 436 else if( "_top".equals( frmTgt ) ) { ptnHref = TOP; } 437 // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..; 438 else if( "RESULT".equals( frmTgt ) || frmTgt == null ) { 439 // 5.6.4.2 (2013/05/17) ある画面で、特殊なターゲット(INPUT,BUTTOMなど)を使用している場合のチェック 440 if( TARGET_CHANGE_SET.contains( fileKey ) ) { 441 ptnHref = PRNT ; 442 } 443 } 444 else { 445 ptnHref = "<input name=\"command\" onClick=\"parent." + frmTgt + ".location.href='" ; 446 // 5.6.4.2 (2013/05/17) ある画面で、特殊なターゲット(INPUT,BUTTOMなど)を使用している場合に記憶 447 TARGET_CHANGE_SET.add( fileKey ); // 別のファイルを処理するときに参照する。 448 } 449 } 450 451 final Matcher mch = PTN_OBJ1.matcher( rtnStr ); 452 int adrs = 0; 453 while( mch.find( adrs ) ) { 454 final String cmd = mch.group(1); 455 if( !cmd.endsWith( "CMD" ) ) { 456 final String val = mch.group(2); 457 final String str1 = ORG + " value=\"" + cmd ; 458 String str2 ; 459 460 if( val != null && val.startsWith( "../" ) ) { 461 str2 = PRNT + val + "'\" value=\"" + cmd ; 462 } 463 // 5.5.2.5 (2012/05/21) update.jsp に出力されるファイルを、コマンド名.htm に出力するように機能追加 464 else if( val != null && val.startsWith( "update" ) ) { 465 str2 = ptnHref + cmd + ".htm'\" value=\"" + cmd ; 466 } 467 else { 468 str2 = ptnHref + val + "'\" value=\"" + cmd ; 469 } 470 rtnStr = rtnStr.replace( str1,str2 ); 471 } 472 adrs = mch.end(); 473 mch.reset( rtnStr ); 474 } 475 476 // 6.2.5.0 (2015/06/05) GMIS V6 対応(location.href時に、type="submit" を type="button" に変更) 477 // 正規表現の置き換え箇所が、難しそうなので、もう一度初めから処理します。 478// // location.href① … type="submit"② … />③ の関係チェック 479 // location.href① … type="submit"② … >③ の関係チェック 480 final StringBuilder buf = new StringBuilder( rtnStr ); 481 482 int idxHref = buf.indexOf( LOC_HREF ); // ① 483 while( idxHref >= 0 ) { 484 final int idxType = buf.indexOf( TP_SUBMIT , idxHref ); // ② 485// final int idxEnd = buf.indexOf( "/>" , idxHref ); // ③ 486 final int idxEnd = buf.indexOf( ">" , idxHref ); // ③ 7.0.1.0 (2018/10/15) 487 if( idxType >= 0 && idxEnd >= 0 && idxType < idxEnd ) { 488 buf.replace( idxType , idxType + TP_SUBMIT.length() , TP_BUTTON ); // 範囲置換 489 } 490 // 6.3.8.0 (2015/09/11) idxEnd = -1 の場合、無限ループになる。(javadoc上では -1 のハズ) 491 idxHref = buf.indexOf( LOC_HREF , Math.max( idxEnd , idxHref + LOC_HREF.length() ) ); 492 } 493 rtnStr = buf.toString(); 494 } 495 return rtnStr; 496 } 497 498 /** 499 * このオブジェクトの文字列表現 500 * "HrefChangeData()" を返します。 501 * 502 * @return 文字列表現 503 * @og.rtnNotNull 504 */ 505 @Override 506 public String toString() { 507 return "HrefChangeData()" ; 508 } 509 } 510 511 /** 512 * 雛形自動作成 で、useAjaxSubmit="true" の対策 513 * 514 * update.jsp で、useAjaxSubmit="true" の場合、entry.htm は、update.jsp の 515 * JavaScriptでforward されるため、雛形には、HTMLの結果は出力されません。 516 * (result.jsp に出力されます。) 517 * そこで、雛形作成時には、entry.htm にJavaScriptを入れて、forward させます。 518 * JavaScript の挿入位置は、 BODYの終了タグがあれば、その直前に、なければ、最後に追加します。 519 * 520 * ※ 6.2.5.0 (2015/06/05) 521 * 本当は、ForwardTag#doEndTag() の noTransitionUrl を出力している箇所に入れれば 522 * 一番きれいだが、各種各画面で使用しているタグなので、あまり変更したくないのと、 523 * style 属性で設定すると、画面が動作しなくなったため、何か問題が起こりそうなので、 524 * 紙芝居作成時のみ対応することとします。 525 * 非表示(display:none;)は、<div id="noTransitionUrl"> の直前にします。 526 * 527 * @og.rev 5.6.3.4 (2013/04/26) entry.htm に "noTransitionUrl" が存在するときの処理。 528 * @og.rev 6.2.5.0 (2015/06/05) GMIS V6 対応(noTransitionUrl,noTransitionTargetを非表示にする) 529 */ 530 private static final class NoTranHrefChangeData extends ChangeData { 531 // 6.2.5.0 (2015/06/05) GMIS V6 対応(noTransitionUrl,noTransitionTargetを非表示にする) 532 private static final String DIV_TAG = "<div id=\"noTransitionUrl\">" ; 533 // 8.1.0.0 (2021/12/28) HTML5 準拠に見直し(type="text/css" 不要) 534// private static final String DISPLAY_NONE = "<style type=\"text/css\">#noTransitionUrl,#noTransitionTarget{display:none;}</style>"; 535 private static final String DISPLAY_NONE = "<style>#noTransitionUrl,#noTransitionTarget{display:none;}</style>"; 536 537 private static final String BODY_END = "</body>" ; 538 // 8.1.0.0 (2021/12/28) HTML5 準拠に見直し(<script> type属性削除) 539// private static final String APPEND_JS = "<script type=\"text/javascript\" src=\"../common/option/noTranHref.js\" ><!-- --></script>" ; 540 private static final String APPEND_JS = "<script src=\"../common/option/noTranHref.js\" ><!-- --></script>" ; 541 542 /** 543 * 実際に変換を行うメソッド。 544 * 545 * @param file 対象ファイル名 546 * @param inStr 対象データ 547 * @return 変換後データ 548 */ 549 @Override 550 public String replace( final String file,final String inStr ) { 551 String rtnStr = inStr; 552 // entry.jsp で、かつ noTransitionUrl 文字列を含む場合のみ 553 if( file.indexOf( "entry" ) >= 0 && inStr.indexOf( "noTransitionUrl" ) >= 0 ) { 554 // 6.2.5.0 (2015/06/05) GMIS V6 対応 555 final StringBuilder buf = new StringBuilder( rtnStr ); 556 final int divAd = buf.indexOf( DIV_TAG ); 557 if( divAd >= 0 ) { buf.insert( divAd,DISPLAY_NONE ); } 558 559 final int adrs = buf.indexOf( BODY_END ); 560 if( adrs >= 0 ) { buf.insert( adrs,APPEND_JS ); } // </body> タグが存在した場合は、その直前に挿入する。 561 else { buf.append( APPEND_JS ); } // 存在しない場合は、最後に挿入する。 562 563 rtnStr = buf.toString(); 564 } 565 return rtnStr; 566 } 567 568 /** 569 * このオブジェクトの文字列表現 570 * "NoTranHrefChangeData()" を返します。 571 * 572 * @return 文字列表現 573 * @og.rtnNotNull 574 */ 575 @Override 576 public String toString() { 577 return "NoTranHrefChangeData()" ; 578 } 579 } 580 581 /** 582 * 雛形自動作成 で、fileDownload の日本語名対応 583 * 584 * 標準的な、fileDownload 処理では、../common/fileDownload.jsp?・・・・GAMENID=XXXX&filename=YYYY" と 585 * なっており、filename 部分は、日本語にも対応できるように urlEncode されています。 586 * これを、元に戻さないとうまくダウンロードできませんでした。 587 * 588 * ※ 参考情報 589 * 1.urlEncode のままで、ファイル名を取得する場合は、下記の標準系で対応可能です。 590 * ,new ChangeData( null ,"../common/fileDownload.htm\\?[^\"]*filename=([^&\"]*)[^\"]*\"","$1\"" ) 591 * 2.ファイル名を、fileDownload.xls 固定にする場合は、下記の標準系で対応可能です。 592 * ,new ChangeData( null ,"../common/fileDownload.htm\\?[^\"]*\"","fileDownload.xls\"" ) 593 * 594 * @og.rev 5.6.4.2 (2013/05/17) 新規追加 595 */ 596 private static final class FileDownloadChangeData extends ChangeData { 597 private static final String PTN1 = "../common/fileDownload.htm\\?[^\"]*filename=([^&\"]*)[^\"]*\"" ; 598 private static final Pattern PTN_OBJ1 = Pattern.compile( PTN1 ); // 6.4.1.1 (2016/01/16) ptnObj1 → PTN_OBJ1 refactoring 599 600 /** 601 * 実際に変換を行うメソッド。 602 * 603 * @param file 対象ファイル名 604 * @param inStr 対象データ 605 * @return 変換後データ 606 */ 607 @Override 608 public String replace( final String file,final String inStr ) { 609 String rtnStr = inStr; 610 // 対象データから、fileDownload.htm を含む場合に処理を実行します。 611 if( rtnStr.indexOf( "../common/fileDownload.htm" ) >= 0 ) { 612 final Matcher mch = PTN_OBJ1.matcher( rtnStr ); 613 int adrs = 0; 614 while( mch.find( adrs ) ) { 615 String fname = mch.group(1); 616 fname = StringUtil.urlDecode( fname ); // デコードしています。 617 618 final int indx = mch.start() ; 619 adrs = mch.end(); 620 rtnStr = rtnStr.substring( 0,indx ) + fname + "\"" + rtnStr.substring( adrs ) ; 621 622 mch.reset( rtnStr ); 623 } 624 } 625 return rtnStr; 626 } 627 628 /** 629 * このオブジェクトの文字列表現 630 * "FileDownloadChangeData()" を返します。 631 * 632 * @return 文字列表現 633 * @og.rtnNotNull 634 */ 635 @Override 636 public String toString() { 637 return "FileDownloadChangeData()" ; 638 } 639 } 640 641 /** 642 * 09_「DIE0005_金型保守_チェック処理ボタン動かない_北林」対応 643 * 644 * @og.rev 6.9.9.2 (2018/09/18) 新規追加 645 * @og.rev 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"/>" 止めを、">" に変更します)。 646 */ 647 private static final class QuerySubmitChange extends ChangeData{ 648// private static final String PTN1 = "<input type=\"hidden\" name=\"" + HybsSystem.NO_XFER_KEY + "(.*)?\" value=\"(.*?\\.htm)\".*?/>" ; 649 private static final String PTN1 = "<input type=\"hidden\" name=\"" + HybsSystem.NO_XFER_KEY + "(.*)?\" value=\"(.*?\\.htm)\".*?>" ; 650 private static final Pattern PTN_OBJ1 = Pattern.compile( PTN1 ); // 6.4.1.1 (2016/01/16) ptnObj1 → PTN_OBJ1 refactoring 651 652 /** 653 * 実際に変換を行うメソッド。 654 * RESULTをターゲットとした画面のみを考慮している。 655 * 656 * @og.rev 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"/>" 止めを、">" に変更します)。 657 * 658 * @param file 対象ファイル名 659 * @param inStr 対象データ 660 * @return 変換後データ 661 */ 662 @Override 663 public String replace( final String file,final String inStr ) { 664 String rtnStr = inStr; 665 666 // query.htmの場合の処理 667 if( file.indexOf( "query.htm" ) >= 0 ) { 668 // hX_XXXのinput type="hidden"のデータを検索 669 // String regex = "<input type=\"hidden\" name=\"" + HybsSystem.NO_XFER_KEY + "(.*)?\" value=\"(.*?\\.htm)\".*?/>"; 670 // Pattern p = Pattern.compile(regex); 671 // Matcher m = p.matcher(rtnStr); 672 final Matcher mch = PTN_OBJ1.matcher( rtnStr ); 673 674 // 存在する場合は input type="submit"のデータを検索して、 675 // 存在する場合はボタンに変換する。 676 // while(m.find()) { 677 while( mch.find() ) { 678 // String name = m.group(1); // 名称 679 // String value = m.group(2); // htm名 680 final String name = mch.group(1); // 名称 681 final String value = mch.group(2); // htm名 682 683// final String regex2 = "<input name=\"command\" value=\"" + name + "\" type=\"submit\" />"; 684 final String regex2 = "<input name=\"command\" value=\"" + name + "\" type=\"submit\" >"; 685// final String af = "<input type=\"button\" onClick=\"parent.RESULT.location.href='" + value + "';\" value=\"" + name + "\"/>"; 686 final String af = "<input type=\"button\" onClick=\"parent.RESULT.location.href='" + value + "';\" value=\"" + name + "\">"; 687 688 rtnStr = rtnStr.replaceFirst( regex2, af ); 689 } 690 } 691 692 return rtnStr; 693 } 694 } 695}