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.html; 017 018import org.opengion.hayabusa.common.HybsSystem; 019import org.opengion.hayabusa.db.DBTableModel; 020import org.opengion.fukurou.security.HybsCryptography; 021import org.opengion.fukurou.security.URLHashMap; 022import org.opengion.fukurou.util.StringUtil; 023import org.opengion.fukurou.util.Attributes; 024import org.opengion.fukurou.util.XHTMLTag; 025import org.opengion.fukurou.model.Formatter; 026 027import java.util.Map; 028import java.util.HashMap; 029import java.util.List; 030import java.util.ArrayList; 031import java.util.Arrays ; 032 033/** 034 * ViewLink インターフェース の実装オブジェクトです。 035 * これを,共通のスーパークラスとして 各種表示フォーム(例:HTML表示等)に使います。 036 * 037 * このクラスは、setter/getterメソッドのデフォルト実装を提供しています。 038 * 各種表示フォームに対応したサブクラス上で, create() をオーバーライドして下さい。 039 * 040 * @og.rev 2.1.0.3 (2002/11/08) エンコードの開始/終了アドレスを求める処理の修正 041 * @og.rev 4.0.0.0 (2005/08/31) 同一カラムの複数登録を許可します。 042 * @og.group 画面表示 043 * 044 * @version 4.0 045 * @author Kazuhiko Hasegawa 046 * @since JDK5.0, 047 */ 048public class ViewLink_LINK implements ViewMarker { 049 private static final String REQ_KEY = HybsSystem.URL_HASH_REQ_KEY ; 050 051 private static final int ACCS_LVL = HybsSystem.sysInt( "URL_ACCESS_SECURITY_LEVEL" ); 052 053 private List<Attributes> markData = null; // 4.0.0 (2005/08/31) 054// private Map<Integer,int[]> formMap_c = new HashMap<Integer,int[]>(); // 3.5.6.1 (2004/06/25) 055// private Map<Integer,String[]> formMap_f = new HashMap<Integer,String[]>(); // 3.5.6.1 (2004/06/25) 056 private Map<Integer,Formatter> formMap = new HashMap<Integer,Formatter>(); 057 private DBTableModel table = null; 058 private int[] markCmlNo = null; 059 private int[] isMark = null; 060 // 2.1.0.3 (2002/11/08) エンコードの開始/終了アドレスを求める処理の修正 061 private int[] encodeIn = null; // 初期値:範囲外 062 private int[] encodeOut = null; // 初期値:範囲外 063 private static final int MARK_NULL = -1; // リンク未設定 064 private static final int MARK_TRUE = 1; // リンク作成 065 private static final int MARK_FALSE = 0; // リンク作成せず 066 // 3.5.2.0 (2003/10/20) 067 private String[] markKey = null; 068 private String[] markLists = null; 069 private int[] markListNo = null; 070 071 private boolean[] useURLCheck = null; // 4.3.7.1 (2009/06/08) 072 private String[] urlCheckUser= null; // 4.3.7.1 (2009/06/08) 073 private long[] urlCheckTime= null; // 4.3.7.1 (2009/06/08) 074 private HybsCryptography[] urlCheckCrypt = null; // 5.8.8.0 (2015/06/05) 075 076 private String[] extToken = null; // 5.8.2.1 (2014/12/13) 077 078 private Map<Integer,List<Integer>> clmMap = new HashMap<Integer,List<Integer>>(); // 4.0.0 (2005/08/31) 079 080 /** 081 * 内容をクリア(初期化)します。 082 * 083 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。 084 * @og.rev 3.5.2.0 (2003/10/20) markLists,markListNo,markKey属性を追加 085 * @og.rev 3.5.6.1 (2004/06/25) formMap属性を追加 086 * @og.rev 4.3.7.1 (2009/06/08) URLチェック属性追加 087 * @og.rev 5.8.2.1 (2014/12/13) extToken追加 088 * @og.rev 5.8.8.0 (2015/06/05) urlCheckCrypt追加 089 */ 090 public void clear() { 091 markData = null; // 4.0.0 (2005/08/31) 092// formMap_c = new HashMap<Integer,int[]>(); // 3.5.6.1 (2004/06/25) 093// formMap_f = new HashMap<Integer,String[]>(); // 3.5.6.1 (2004/06/25) 094 formMap = new HashMap<Integer,Formatter>(); 095 table = null; 096 isMark = null; 097 encodeIn = null; 098 encodeOut = null; 099 markKey = null; 100 markLists = null; 101 markListNo = null; 102 clmMap = new HashMap<Integer,List<Integer>>(); // 4.0.0 (2005/08/31) 103 useURLCheck = null; // 4.3.7.1 (2009/06/08) 104 urlCheckUser= null; // 4.3.7.1 (2009/06/08) 105 urlCheckTime= null; // 4.3.7.1 (2009/06/08) 106 extToken = null; // 5.8.2.1 (2014/12/14) 107 urlCheckCrypt = null; // 5.8.8.0 (2015/06/05) 108 } 109 110 /** 111 * カラムに対するリンクアトリビュートをセットします。 112 * 113 * @og.rev 3.1.0.0 (2003/03/20) Hashtable を使用している箇所で、非同期でも構わない箇所を、HashMap に置換え。 114 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。 115 * @og.rev 4.0.0.0 (2005/08/31) 同一カラムの複数登録を許可します。 116 * 117 * @param attri リンクアトリビュート 118 */ 119 public void addAttribute( final Attributes attri ) { 120 if( markData == null ) { markData = new ArrayList<Attributes>(); } 121 markData.add( attri ); 122 } 123 124 /** 125 * 内部に DBTableModel をセットします。 126 * 127 * @og.rev 2.1.0.3 (2002/11/08) エンコードの開始/終了アドレスを求める処理の修正 128 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。 129 * @og.rev 3.5.2.0 (2003/10/20) markLists,markListNo,markKey属性を追加 130 * @og.rev 3.5.5.0 (2004/03/12) xlink 属性によるリンク情報作成方法の分岐を追加 131 * @og.rev 3.5.6.1 (2004/06/25) DBTableModel の再設定に対応。 132 * @og.rev 3.5.6.2 (2004/07/05) linkFormat をパラメータで取得するように変更。 133 * @og.rev 3.8.1.1 (2005/11/21) linkFormat が "[","]" をエンコードしてしまった場合に元に戻します。 134 * @og.rev 4.0.0.0 (2005/08/31) 同一カラムの複数登録を許可します。 135 * @og.rev 4.3.7.1 (2009/06/08) URLチェック機能追加 136 * @og.rev 5.8.8.0 (2015/06/05) urlCheckCrypt対応 137 * 138 * @param tbl DBTableModelオブジェクト 139 */ 140 public void setDBTableModel( final DBTableModel tbl ) { 141 table = tbl; 142// String linkFormat = null; 143 int count = markData.size(); // 4.0.0 (2005/08/31) 144 145 isMark = new int[ count ]; 146 markKey = new String[ count ]; 147 markCmlNo = new int[ count ]; 148 markLists = new String[ count ]; 149 markListNo = new int[ count ]; 150 encodeIn = new int[ count ]; 151 encodeOut = new int[ count ]; 152 useURLCheck = new boolean[ count ]; // 4.3.7.1 (2009/06/08) 153 urlCheckUser= new String[ count ]; // 4.3.7.1 (2009/06/08) 154 urlCheckTime= new long[ count ]; // 4.3.7.1 (2009/06/08) 155 extToken = new String[ count ]; // 5.8.2.1 (2014/12/13) 156 urlCheckCrypt= new HybsCryptography[ count ]; // 5.8.8.0 (2015/06/05) 157 158 Arrays.fill( isMark,MARK_FALSE ); // リンクの表示可否 159 Arrays.fill( markCmlNo,-1 ); // リンクの可否を判断するカラム番号 160 Arrays.fill( encodeIn ,10000 ); // 初期値:範囲外 161 Arrays.fill( encodeOut,-1 ); // 初期値:範囲外 162 Arrays.fill( useURLCheck, false ); // 4.3.7.1 (2009/06/08) 163 Arrays.fill( urlCheckTime, 0L ); // 4.3.7.1 (2009/06/08) 164 165 // 4.0.0 (2005/08/31) 同一カラムの複数登録を許可します。 166 for( int intKey=0; intKey<count; intKey++ ) { 167 Attributes attri = markData.get( intKey ); 168 169 String column = attri.get( "column" ); 170 int clm = table.getColumnNo( column ); 171 List<Integer> list = clmMap.get( clm ); 172 if( list == null ) { list = new ArrayList<Integer>(); } 173 list.add( intKey ); 174 clmMap.put( clm,list ); 175 176 String linkFormat = attri.get( "linkFormat" ); 177 linkFormat = StringUtil.replace( linkFormat,"%5B","[" ); // 3.8.1.1 (2005/11/21) 178 linkFormat = StringUtil.replace( linkFormat,"%5D","]" ); // 3.8.1.1 (2005/11/21) 179 180// makeFormat( intKey,linkFormat ); 181 Formatter formatter = new Formatter( table ); 182 formatter.setFormat( linkFormat ); 183 formMap.put( intKey, formatter ); 184 185 // URLエンコード用の範囲設定。この範囲内のデータをURLエンコードする。 186 String[] format = formatter.getFormat(); 187 boolean findHref = false; 188 for( int j=0; j<format.length; j++ ) { 189 if( format[j] != null && format[j].indexOf( "href" ) >= 0 ) { findHref = true; } 190 if( findHref && format[j].indexOf( '?' ) >= 0 ) { encodeIn[intKey] = j; } 191 if( findHref && format[j].indexOf( "\" " ) >= 0 ) { encodeOut[intKey] = j; findHref = false; } 192 } 193 194 // 4.3.7.1 (2009/06/08) 195 useURLCheck[intKey] = StringUtil.nval( attri.get( "useURLCheck" ), false ); 196 urlCheckUser[intKey] = StringUtil.nval( attri.get( "urlCheckUser" ), null ); 197 urlCheckTime[intKey] = StringUtil.nval( attri.get( "urlCheckTime" ), 0L ); 198 urlCheckCrypt[intKey] = new HybsCryptography(StringUtil.nval( attri.get( "urlCheckCrypt" ), null )); // 5.8.8.0 (2015/06/05) 199 200 extToken[intKey] = StringUtil.nval( attri.get("extToken"),null); // 5.8.2.1 (2014/12/14) 201 202 makeOnLinkFormat( intKey,attri ); 203 } 204 } 205 206 /** 207 * 指定の行列に対するマーカー文字列を返します。 208 * この値は,すでにマーカー文字列処理されている為, RendererValue で 209 * 変換する必要はありません。 210 * 引数の value はそのカラムの値として利用されます。この値は、修飾済みの 211 * 値を与えることが可能です。 212 * 213 * @og.rev 2.1.0.3 (2002/11/08) エンコードの開始/終了アドレスを求める処理の修正 214 * @og.rev 3.0.0.0 (2002/12/25) URLEncoder.encode を StringUtil#urlEncode に置換え 215 * @og.rev 3.0.0.1 (2003/02/14) リンクの引数部分に、RendererValue が適用される箇所を修正 216 * @og.rev 3.0.0.1 (2003/02/14) リンクの引数部分に、RendererValue が適用される箇所を修正 217 * @og.rev 3.5.6.1 (2004/06/25) formMap属性を使用します。 218 * @og.rev 3.7.0.3 (2005/03/01) "{I}" 文字列に、行番号(row)を割り当てます。 219 * @og.rev 3.8.5.0 (2006/03/20) "{I}" ⇒ "%7BI%7D" として、行番号(row)を割り当てます。 220 * @og.rev 4.3.7.1 (2009/06/08) URLチェック機能追加 221 * @og.rev 4.3.7.4 (2009/07/01) 循環参照を解消 222 * @og.rev 5.2.3.0 (2010/12/01) URLのハッシュ化/暗号化を行います。 223 * @og.rev 5.8.2.1 (2014/12/13) トークンプラグイン対応 224 * @og.rev 5.8.8.0 (2015/06/05) urlCheckCrypt対応 225 * 226 * @param row 指定の行 227 * @param clm 指定の列 228 * @param value カラムの値 229 * 230 * @return row行,colum列 のマーカー文字列 231 */ 232 public String getMarkerString( final int row,final int clm,final String value ) { 233 int intKey = isOnLink(row,clm) ; 234 if( intKey < 0 ) { return value; } 235 236 Formatter formatter = formMap.get( intKey ); 237 int[] clmNo = formatter.getClmNos(); 238 String[] format = formatter.getFormat(); 239 240// int[] clmNo = formMap_c.get( intKey ); 241// String[] format = formMap_f.get( intKey ); 242 243 StringBuilder strLink = new StringBuilder( HybsSystem.BUFFER_LARGE ); 244 int j=0; 245 String val ; 246 for( ; j<clmNo.length; j++ ) { 247 strLink.append( format[j] ); 248 if( encodeIn[intKey] <= j && j < encodeOut[intKey] ) { 249// val = table.getValue(row,clmNo[j]); 250 val = formatter.getValue(row,clmNo[j]); 251 strLink.append( StringUtil.urlEncode( val ) ); 252 } 253 else if( clm == clmNo[j] ) { 254 strLink.append( value ); 255 } 256 else { 257// val = table.getValue(row,clmNo[j]); 258 val = formatter.getValue(row,clmNo[j]); 259 strLink.append( val ); 260 } 261 } 262 strLink.append( format[j] ); 263 264 // 3.8.5.0 (2006/03/27) "{I}" と そのエンコード文字 "%7BI%7D" に、行番号(row)を割り当てます。 265 String rtn = strLink.toString(); 266 String sRow = String.valueOf( row ); 267 rtn = StringUtil.replace( rtn,"{I}",sRow ); 268 rtn = StringUtil.replace( rtn,"%7BI%7D",sRow ); 269 270 // 4.3.7.1 (2009/06/08) 271 if( useURLCheck[intKey] ) { 272 // 4.3.7.4 (2009/07/01) 273// rtn = XHTMLTag.embedURLCheckKey( rtn, HybsSystem.URL_CHECK_KEY, urlCheckUser[intKey], urlCheckTime[intKey] ); 274 rtn = XHTMLTag.embedURLCheckKey( rtn, HybsSystem.URL_CHECK_KEY, urlCheckUser[intKey], urlCheckTime[intKey], urlCheckCrypt[intKey] ); // 5.8.8.0 (2015/06/05) 275 } 276 277 // 5.8.2.1 (2014/12/13) トークンプラグイン対応 278 if( extToken[intKey] != null && extToken[intKey].length() > 0 ){ 279 String[] tokens = StringUtil.csv2Array( extToken[intKey] ); 280 for( String tk :tokens ){ 281 String cls = HybsSystem.sys( "CreateToken_" + tk ) ; 282 CreateToken ct = (CreateToken)HybsSystem.newInstance( cls ); 283 rtn = ct.embedToken( rtn, urlCheckTime[intKey], null ); 284 } 285 } 286 287 288 289 // 5.2.3.0 (2010/12/01) URLのハッシュ化/暗号化 290 if( ACCS_LVL == 2 ) { 291 // ACCS_LVL == 2 の場合は、外部のみ処理するので、extOnly=true をセットする。 292 rtn = URLHashMap.makeUrlChange( rtn,REQ_KEY,true ); 293 } 294 else if( ACCS_LVL == 3 ) { 295 rtn = URLHashMap.makeUrlChange( rtn,REQ_KEY,false ); 296 } 297 298 return rtn ; 299 } 300 301 /** 302 * リンクフォーマットを作成します。 303 * 304 * @og.rev 2.1.0.3 (2002/11/08) エンコードの開始/終了アドレスを求める処理の修正 305 * @og.rev 3.5.6.1 (2004/06/25) formMap属性を使用します。 306 * 307 * @param intKey カラムキーの番号 308 * @param fmt フォーマット文字列 309 */ 310// private void makeFormat( final int intKey,final String fmt ) { 311// boolean findHref = false; 312// 313// StringTokenizer token = new StringTokenizer( fmt,"[]" ); 314// int count = token.countTokens() / 2 ; 315// int[] clmNo = new int[ count ]; 316// String[] format = new String[ count+1 ]; 317// for( int j=0; j<count; j++ ) { 318// format[j] = token.nextToken(); 319// clmNo[j] = table.getColumnNo( token.nextToken() ); 320// 321// // URLエンコード用の範囲設定。この範囲内のデータをURLエンコードする。 322// if( format[j] != null && format[j].indexOf( "href" ) >= 0 ) { findHref = true; } 323// if( findHref && format[j].indexOf( '?' ) >= 0 ) { encodeIn[intKey] = j; } 324// if( findHref && format[j].indexOf( "\" " ) >= 0 ) { encodeOut[intKey] = j; findHref = false; } 325// } 326// format[count] = token.nextToken(); 327// formMap_c.put( intKey, clmNo ); 328// formMap_f.put( intKey, format ); 329// 330// if( format[count] != null && format[count].indexOf( "href" ) >= 0 ) { findHref = true; } 331// if( findHref && format[count].indexOf( '?' ) >= 0 ) { encodeIn[intKey] = count; } 332// if( findHref && format[count].indexOf( "\" " ) >= 0 ) { encodeOut[intKey] = count; } 333// } 334 335 /** 336 * リンクを張る/張らないの指定カラム番号を求めます。 337 * また、int[列番号] isMark を初期化します。 338 * 339 * @og.rev 3.5.2.0 (2003/10/20) markLists,markListNo,markKey属性を追加 340 * 341 * @param intKey カラムキーの番号 342 * @param attri アトリビュート 343 */ 344 private void makeOnLinkFormat( final int intKey,final Attributes attri ) { 345 String onMark = attri.get( "onLink" ); 346 String markList = attri.get( "markList" ); 347 348 // 3.5.6.0 (2004/06/18) nullポインタの参照外しバグの対応 349 // このロジックで値が設定済みであれば、以下の処理は不要である。 350 isMark[intKey] = MARK_NULL; 351 if( onMark == null || onMark.length() == 0 || 352 markList == null || markList.length() == 0 ) { 353 isMark[intKey] = MARK_FALSE; 354 return ; // 3.5.6.0 (2004/06/18) 355 } 356 else if( onMark.charAt( 0 ) != '[' && markList.charAt( 0 ) != '[' ) { 357 isMark[intKey] = ( markList.indexOf( onMark ) >= 0 ) ? MARK_TRUE : MARK_FALSE; 358 return ; // 3.5.6.0 (2004/06/18) 359 } 360 361 if( onMark.charAt( 0 ) == '[' ) { 362 markCmlNo[intKey] = table.getColumnNo( onMark.substring( 1,onMark.length()-1 )); 363 } 364 else { 365 markCmlNo[intKey] = -1; 366 markKey[intKey] = onMark ; 367 } 368 369 if( markList.charAt( 0 ) == '[' ) { 370 markListNo[intKey] = table.getColumnNo( markList.substring( 1,markList.length()-1 )); 371 } 372 else { 373 markListNo[intKey] = -1; 374 markLists[intKey] = markList; 375 } 376 } 377 378 /** 379 * リンクを張るかどうかを判断します。 380 * int[列番号] isMark には、 未設定 FALSE TRUE の状態を持っており、 381 * 列でリンクを張る状態が固定の場合(例えば,onLink属性がデフォルト "true" の場合) 382 * カラムに関係なく、同じ値を返すときに、使用します。 383 * 384 * @og.rev 3.5.2.0 (2003/10/20) markLists,markListNo,markKey属性を追加 385 * @og.rev 3.5.4.0 (2003/11/25) onMark ,markList が null(またはゼロストリング)の場合は、false とする。 386 * @og.rev 4.0.0.0 (2005/08/31) 同一カラムの複数登録を許可します。 387 * 388 * @param row 列番号 389 * @param clm カラムキーの名称 390 * 391 * @return 処理するリスト番号、-1 の場合は、該当なし 392 */ 393 private int isOnLink( final int row,final int clm ) { 394 395 List<Integer> list = clmMap.get( clm ); 396 if( list == null ) { return -1; } 397 398 for( int i=0; i<list.size(); i++ ) { 399 int intKey = list.get( i ); 400 if( isMark[intKey] != MARK_NULL ) { 401 if( isMark[intKey] == MARK_TRUE ) { return intKey; } 402 else { continue; } 403 } 404 405 String onMark ; 406 if( markCmlNo[intKey] < 0 ) { onMark = markKey[intKey] ; } 407 else { onMark = table.getValue( row,markCmlNo[intKey] ); } 408 409 // 3.5.4.0 (2003/11/25) 追加 410 if( onMark == null || onMark.length() == 0 ) { continue; } 411 412 String markList ; 413 if( markListNo[intKey] < 0 ) { markList = markLists[intKey] ; } 414 else { markList = table.getValue( row,markListNo[intKey] ); } 415 416 // 3.5.4.0 (2003/11/25) 修正 417 if( markList == null || markList.length() == 0 ) { continue; } 418 419 if( markList.indexOf( onMark ) >= 0 ) { return intKey; } 420 } 421 return -1; 422 } 423 424 /** 425 * マーカーされたカラム番号の配列を返します。 426 * 427 * これは特殊処理で、Edit機能で、カラム列をキャッシュしているときに、 428 * JSPのソース等の変更時に、変更が反映されない対応を行う場合、 429 * 通常の ViewFormのサブクラスから、Edit専用の ViewForm_HTMLSeqClmTable で 430 * 制御する場合、ViewMarkerのEditMarkerでは、通常非表示(検索の場合)ですが 431 * Editのポップアップ画面に、表示されてしまうのを避けるため、noDisplay に 432 * 強制的にするカラム番号が必要です。 433 * あくまで、暫定処置です。Edit機能を改修するときに、この機能は削除します。 434 * 435 * ※ この処理は、EditMarkerでのみ有効にします。 436 * 437 * @og.rev 5.8.6.0 (2015/04/03) 6.0.3.0の移植 438 * 439 * @return マーカーされたカラム番号の配列(常に、長さ0の配列を返す) 440 */ 441 public int[] getColumnNos() { 442 return new int[0]; 443 } 444}