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