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.taglib; 017 018import static org.opengion.fukurou.util.StringUtil.*; 019 020import java.io.File; 021import java.io.FileFilter; 022import java.io.IOException; 023import java.io.ObjectInputStream; 024import java.io.ObjectOutputStream; 025import java.io.Serializable; 026import java.util.Arrays; 027import java.util.Comparator; 028 029import org.opengion.fukurou.util.Attributes; 030import org.opengion.fukurou.util.StringUtil; 031import org.opengion.fukurou.util.XHTMLTag; 032import org.opengion.hayabusa.common.HybsSystem; 033import org.opengion.hayabusa.common.HybsSystemException; 034import org.opengion.hayabusa.io.HybsFileOperationFactory; 035 036/** 037 * ファイルのプルダウンリストの作成するタグです。 038 * 039 * SelectタグのBODY部に指定します。 040 * 並び替えについては、このタグで指定しますが、ファイルの選別は、 041 * BODY 部に記述する fileWhere タグで指定します。 042 * 043 * @og.formSample 044 * ●形式:<og:fileOption from="…" value="[…]" ・・・ >・・・</og:fileOption> 045 * ●body:あり(EVAL_BODY_BUFFERED:BODYを評価し、{@XXXX} を解析します) 046 * 047 * ●Tag定義: 048 * <og:fileOption 049 * from 【TAG】ファイルの検索元となるディレクトリを指定します (初期値:FILE_URL[=filetemp/]) 050 * value 【TAG】Optionの初期値で選ばれる値を指定します 051 * orderBy 【TAG】検索した結果を表示する表示順をファイル属性名で指定します(初期値:自然順序) 052 * desc 【TAG】表示順を逆転するかどうか[true/false]を指定します(初期値:false) 053 * storageType 【TAG】読み取り元ストレージタイプを指定します(初期値:CLOUD_TARGET) 054 * bucketName 【TAG】読み取り元バケット名を指定します(初期値:CLOUD_BUCKET) 055 * debug 【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false) 056 * > ... Body ... 057 * </og:fileOption> 058 * 059 * ●使用例 060 * ・<og:fileOption val1="ABCD" val2="{@value}" > 061 * <og:fileWhere startsWith="ABCD" ・・・ /> 062 * </og:fileOption> 063 * 064 * @og.rev 2.1.1.0 (2002/11/11) 新規作成 065 * @og.rev 4.0.0.0 (2005/01/31) 内部ロジック改定 066 * @og.rev 5.10.9.0 (2019/03/01) oota クラウドストレージ対応を追加。(Fileクラスを拡張) 067 * @og.group その他入力 068 * 069 * @version 4.0 070 * @author Kazuhiko Hasegawa 071 * @since JDK5.0, 072 */ 073public class FileOptionTag extends CommonTagSupport { 074 //* このプログラムのVERSION文字列を設定します。 {@value} */ 075 private static final String VERSION = "5.3.4.0 (2011/04/01)" ; 076 077 private static final long serialVersionUID = 534020110401L ; 078 079 private String orderBy = null; // ソート項目 080 private boolean desc = false; // 降順フラグ 081 private String from = HybsSystem.sys( "FILE_URL" ); // 検索起点ファイル 082 private String selValue = null; // 選択済み初期値にする場合 083 private String storageType = null; // 5.10.9.0 (2019/03/01) クラウドストレージタイプ 084 private String bucketName = null; // 5.10.9.0 (2019/03/01) バケット名 085 086 private transient FileFilter filter = null; // FileWhere で指定したフィルター 087 088 private static final String[] ORDER_BY = new String[] { 089 "NAME","LASTMODIFIED","FILE_LENGTH","LENGTH" }; // 5.3.4.0 (2011/04/01) FILE_LENGTH 追加 090 091 /** 092 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。 093 * 094 * @return 後続処理の指示( EVAL_BODY_BUFFERED ) 095 */ 096 @Override 097 public int doStartTag() { 098 return( EVAL_BODY_BUFFERED ); // Body を評価する。( extends BodyTagSupport 時) 099 } 100 101 /** 102 * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。 103 * 104 * @return 後続処理の指示(SKIP_BODY) 105 */ 106 @Override 107 public int doAfterBody() { 108 return(SKIP_BODY); 109 } 110 111 /** 112 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。 113 * 114 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。 115 * 116 * @return 後続処理の指示 117 */ 118 @Override 119 public int doEndTag() { 120 debugPrint(); // 4.0.0 (2005/02/28) 121// SelectTag select = (SelectTag)findAncestorWithClass( this, SelectTag.class ); 122 OptionAncestorIF select = (OptionAncestorIF)findAncestorWithClass( this, OptionAncestorIF.class ); 123 if( select == null ) { 124// String errMsg = "このタグは、SelectTag のBODY に記述する必要があります。"; 125 String errMsg = "<b>" + getTagName() + "タグは、SelectTag または、DatalistTag のBODY に記述する必要があります。</b>"; 126 throw new HybsSystemException( errMsg ); 127 } 128 Comparator<File> comp = makeComparator( orderBy,desc ); 129 makeLabel( select,comp ); 130 131 return(EVAL_PAGE); 132 } 133 134 /** 135 * タグリブオブジェクトをリリースします。 136 * キャッシュされて再利用されるので、フィールドの初期設定を行います。 137 * 138 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。 139 * @og.rev 5.10.9.0 (2019/03/01) storageType,bucketName属性を追加 140 * 141 */ 142 @Override 143 protected void release2() { 144 super.release2(); 145 orderBy = null; // ソート項目 146 desc = false; // 降順フラグ 147 from = HybsSystem.sys( "FILE_URL" ); 148 filter = null; 149 selValue = null; 150 storageType = null; // 5.10.9.0 (2019/03/01) 151 bucketName = null; // 5.10.9.0 (2019/03/01) 152 } 153 154 /** 155 * オプションを作成します。 156 * 157 * ファイル名を "value" に、 158 * BODY属性 に登録するOptionを作成します。 159 * 160 * @og.rev 5.3.4.0 (2011/04/01) FILE_LENGTH 追加 161 * 162 * @param orderBy ソートする属性[NAME/LASTMODIFIED/FILE_LENGTH/LENGTH] 163 * @param desc 並び順[true:昇順/false:降順] 164 * 165 * @return ファイル比較用のComparatorオブジェクト 166 */ 167 private Comparator<File> makeComparator( final String orderBy,final boolean desc ) { 168 if( orderBy == null ) { return null; } 169 170 Comparator<File> comp = null ; 171 172 if( "NAME".equalsIgnoreCase( orderBy ) ) { 173 comp = new NameComparator( desc ); 174 } 175 else if( "LASTMODIFIED".equalsIgnoreCase( orderBy ) ) { 176 comp = new ModifiedComparator( desc ); 177 } 178 // "LENGTH" を残すのは、互換性のため 179 else if( "FILE_LENGTH".equalsIgnoreCase( orderBy ) || "LENGTH".equalsIgnoreCase( orderBy ) ) { 180 comp = new LengthComparator( desc ); 181 } 182 183 return comp ; 184 } 185 186 /** 187 * オプションを作成します。 188 * 189 * ファイル名を "value" に、 190 * BODY属性 に登録するOptionを作成します。 191 * 192 * @og.rev 3.8.0.9 (2005/10/17) 複数選択可能時に全選択を設定する。 193 * @og.rev 5.10.9.0 (2019/03/01) クラウドストレージ対応。 194 * 195 * @param select SelectTagオブジェクト 196 * @param comp 並び順を指定するためのComparatorオブジェクト 197 */ 198// private void makeLabel( final SelectTag select,final Comparator<File> comp ) { 199 private void makeLabel( final OptionAncestorIF select,final Comparator<File> comp ) { 200 // 5.10.9.0 (2019/03/01) MODIFY 201 // File path = new File( from ); 202 File path = HybsFileOperationFactory.create(storageType, bucketName, from); 203// File[] list = path.listFiles( filter ); 204 if(filter == null) { 205 throw new HybsSystemException("fileOptionタグにはfileWhereタグをBodyに設定して下さい"); 206 } 207 File[] list = path.listFiles( filter ); 208 209 boolean multipleAll = select.isMultipleAll(); // 3.8.0.9 (2005/10/17) 210 if( list != null ) { 211 Arrays.sort( list, comp ); 212 213 for( int i = 0; i < list.length; i++ ) { 214 if( list[i].isDirectory() ) { continue; } // ディレクトリは除外 215 Attributes attri = new Attributes(); 216 String value = list[i].getName(); 217 attri.set( "value", value ); 218 if( ( selValue != null && selValue.equalsIgnoreCase( value ) ) || multipleAll ) { 219 attri.set( "selected", "selected" ); 220 } 221 attri.set( "body", value ); 222 select.addOption( XHTMLTag.option( attri ) ); 223 } 224 } 225 } 226 227 /** 228 * 【TAG】Optionの初期値で選ばれる値を指定します。 229 * 230 * @og.tag 231 * キーになるのは、ファイル属性の NAME です。(ディレクトリなしのファイル名) 232 * ここで value属性に指定した場合、このファイル名と(大文字小文字を無視して) 233 * 一致する場合に、プルダウンの初期値に表示されます。(selected 属性が設定される。) 234 * 235 * @param val 初期値で選ばれる値 236 */ 237 public void setValue( final String val ) { 238 selValue = nval( getRequestParameter( val ),selValue ); 239 } 240 241 /** 242 * 【TAG】ファイルの検索元となるディレクトリを指定します 243 * (初期値:FILE_URL[={@og.value org.opengion.hayabusa.common.SystemData#FILE_URL}])。 244 * 245 * @og.tag ファイルの検索元となるディレクトリを指定します。 246 * (初期値:システム定数のFILE_URL[={@og.value org.opengion.hayabusa.common.SystemData#FILE_URL}])。 247 * 248 * @og.rev 4.0.0.0 (2007/11/20) 指定されたディレクトリ名の最後が"\"or"/"で終わっていない場合に、"/"を付加する。 249 * 250 * @param url ファイルの検索元となるディレクトリ 251 * @see org.opengion.hayabusa.common.SystemData#FILE_URL 252 */ 253 public void setFrom( final String url ) { 254 String furl = nval( getRequestParameter( url ),null ); 255 if( furl != null ) { 256 char ch = furl.charAt( furl.length()-1 ); 257 if( ch != '/' && ch != '\\' ) { furl = furl + "/"; } 258 } 259 furl = StringUtil.urlAppend( from,furl ); 260 furl = StringUtil.urlAppend( furl,"." ); 261 from = HybsSystem.url2dir( furl ); 262 } 263 264 /** 265 * 【TAG】検索した結果を表示する表示順をファイル属性名で指定します(初期値:自然順序)。 266 * 267 * @og.tag 268 * ファイルをソートする順(Comparator)を指定します。ソートに指定できる 269 * ファイル属性名は、"NAME","LASTMODIFIED","FILE_LENGTH" の内のどれかひとつです。 270 * 何も指定しない場合は、Fileオブジェクトの自然順序でのソートになります。 271 * (※ 下位互換性のため、LENGTH も残しますが、廃止予定です。) 272 * 273 * @og.rev 3.5.6.2 (2004/07/05) 文字列の連結にStringBuilderを使用します。 274 * @og.rev 4.0.0.0 (2005/01/31) 新規ロジックで改定 275 * @og.rev 5.3.4.0 (2011/04/01) ORDER_BYリストの出力方法 見直し 276 * 277 * @param ordr ソートキー("NAME","LASTMODIFIED","FILE_LENGTH") 278 */ 279 public void setOrderBy( final String ordr ) { 280 orderBy = nval( getRequestParameter( ordr ),orderBy ); 281 282 if( orderBy != null && ! check( orderBy, ORDER_BY ) ) { 283 StringBuilder errMsg = new StringBuilder(); 284 errMsg.append( "orderBy 属性に、下記の属性名以外の値が設定されました。" ); 285 errMsg.append( HybsSystem.CR ); 286 errMsg.append( " orderBy=[" ).append( orderBy ).append( "]" ); 287 errMsg.append( HybsSystem.CR ); 288 errMsg.append( " orderBy List=[" ); 289 errMsg.append( StringUtil.array2csv( ORDER_BY ) ); 290 errMsg.append( "]" ); 291// for( int i=0; i<ORDER_BY.length; i++ ) { 292// errMsg.append( ORDER_BY[i] ); 293// if( i == ORDER_BY.length-1 ) { errMsg.append( "]" ); } 294// else { errMsg.append( "," ); } 295// } 296 throw new HybsSystemException( errMsg.toString() ); 297 } 298 } 299 300 /** 301 * 【TAG】表示順を逆転するかどうか[true/false]を指定します(初期値:false)。 302 * 303 * @og.tag 304 * orderBy 属性で指定した表示順を、逆順にするかどうかを指定できます。 305 * 初期値は、false (昇順) です。 306 * 307 * @param flag 表示順を逆転するかどうか [true:逆順/false:昇順] 308 */ 309 public void setDesc( final String flag ) { 310 desc = nval( getRequestParameter( flag ),desc ); 311 } 312 313 /** 314 * FileFilterオブジェクトをセットします。 315 * これは、BODY 部に登録した、FileWhereタグによって設定された 316 * ファイルフィルターです。 317 * 318 * @param filter オブジェクト 319 */ 320 protected void setFileFilter( final FileFilter filter ) { 321 this.filter = filter; 322 } 323 324 /** 325 * 名前順でのソート順を指定する Comparator の実体内部クラス 326 * 327 * @og.group その他入力 328 * 329 * @version 4.0 330 * @author Kazuhiko Hasegawa 331 * @since JDK5.0, 332 */ 333 static class NameComparator implements Comparator<File>,Serializable { 334 private static final long serialVersionUID = 4000 ; 335 336 private final boolean desc ; 337 338 /** 339 * 名前順での比較を行うオブジェクトを作成します。 340 * 341 * @param desc [true:昇順/false:降順] 342 */ 343 public NameComparator( final boolean desc ) { this.desc = desc; } 344 345 /** 346 * Comparator インターフェースの compare( File,File ) メソッド 347 * 348 * @param o1 File 比較元1のファイルオブジェクト 349 * @param o2 File 比較元2のファイルオブジェクト 350 */ 351 public int compare( final File o1, final File o2 ) { 352 File f1 = (desc) ? o2 : o1 ; 353 File f2 = (desc) ? o1 : o2 ; 354 return (f1.getName()).compareTo( f2.getName() ) ; 355 } 356 } 357 358 /** 359 * 更新日順でのソート順を指定する Comparator の実体内部クラス 360 * 361 * @og.group その他入力 362 * 363 * @version 4.0 364 * @author Kazuhiko Hasegawa 365 * @since JDK5.0, 366 */ 367 static class ModifiedComparator implements Comparator<File>,Serializable { 368 private static final long serialVersionUID = 4000 ; 369 370 private final boolean desc ; 371 372 /** 373 * 更新日順での比較を行うオブジェクトを作成します。 374 * 375 * @param desc [true:昇順/false:降順] 376 */ 377 public ModifiedComparator( final boolean desc ) { this.desc = desc; } 378 379 /** 380 * Comparator インターフェースの compare( File,File ) メソッド 381 * 382 * @param o1 File 比較元1のファイルオブジェクト 383 * @param o2 File 比較元2のファイルオブジェクト 384 */ 385 public int compare( final File o1, final File o2 ) { 386 File f1 = (desc) ? o2 : o1 ; 387 File f2 = (desc) ? o1 : o2 ; 388 return (int)( f1.lastModified() - f2.lastModified() ) ; 389 } 390 } 391 392 /** 393 * ファイルサイズ順でのソート順を指定する Comparator の実体内部クラス 394 * 395 * @og.group その他入力 396 * 397 * @version 4.0 398 * @author Kazuhiko Hasegawa 399 * @since JDK5.0, 400 */ 401 static class LengthComparator implements Comparator<File>,Serializable { 402 private static final long serialVersionUID = 4000 ; 403 404 private final boolean desc ; 405 406 /** 407 * ファイルサイズでの比較を行うオブジェクトを作成します。 408 * 409 * @param desc [true:昇順/false:降順] 410 */ 411 public LengthComparator( final boolean desc ) { this.desc = desc; } 412 413 /** 414 * Comparator インターフェースの compare( File,File ) メソッド 415 * 416 * @param o1 File 比較元1のファイルオブジェクト 417 * @param o2 File 比較元2のファイルオブジェクト 418 */ 419 public int compare( final File o1, final File o2 ) { 420 File f1 = (desc) ? o2 : o1 ; 421 File f2 = (desc) ? o1 : o2 ; 422 return (int)( f1.length() - f2.length() ) ; 423 } 424 } 425 426 /** 427 * シリアライズ用のカスタムシリアライズ書き込みメソッド 428 * 429 * @og.rev 4.0.0.0 (2006/09/31) 新規追加 430 * @serialData 一部のオブジェクトは、シリアライズされません。 431 * 432 * @param strm ObjectOutputStreamオブジェクト 433 * @throws IOException シリアライズに関する入出力エラーが発生した場合 434 */ 435 private void writeObject( final ObjectOutputStream strm ) throws IOException { 436 strm.defaultWriteObject(); 437 } 438 439 /** 440 * シリアライズ用のカスタムシリアライズ読み込みメソッド 441 * 442 * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。 443 * 444 * @og.rev 4.0.0.0 (2006/09/31) 新規追加 445 * @serialData 一部のオブジェクトは、シリアライズされません。 446 * 447 * @param strm ObjectInputStreamオブジェクト 448 * @see #release2() 449 * @throws IOException シリアライズに関する入出力エラーが発生した場合 450 * @throws ClassNotFoundException クラスを見つけることができなかった場合 451 */ 452 private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException { 453 strm.defaultReadObject(); 454 } 455 456 /** 457 * 【TAG】読み取り元ストレージタイプを設定します。 458 * 459 * @og.tag 460 * ファイルを読み取り元の、ストレージタイプを設定します。 461 * 未設定の場合は、システムリソースの「CLOUD_TARGET」が参照されます。 462 * 自身のサーバを指定する場合は、「default」を設定してください。 463 * 464 * @og.rev 5.10.9.0 (2019/03/01) 新規追加 465 * 466 * @param storage ストレージタイプ 467 */ 468 public void setStorageType( final String storage ) { 469 storageType = nval( getRequestParameter( storage ), storageType ); 470 } 471 472 /** 473 * 【TAG】読み取り元バケット名を設定します。 474 * 475 * @og.tag 476 * ファイルを読み取り元の、バケット名を指定します。 477 * クラウドストレージ利用時のみ有効です。 478 * 未設定の場合は、システムリソースの「CLOUD_BUKET」が参照されます。 479 * 480 * @og.rev 5.10.9.0 (2019/03/01) 新規追加 481 * 482 * @param bucket バケット名 483 */ 484 public void setBucketName( final String bucket ) { 485 bucketName = nval( getRequestParameter( bucket ), bucketName ); 486 } 487 488 /** 489 * このオブジェクトの文字列表現を返します。 490 * 基本的にデバッグ目的に使用します。 491 * 492 * @og.rev 5.10.9.0 (2019/03/01) storageType,bucketNameを出力対象に追加。 493 * 494 * @return このクラスの文字列表現 495 */ 496 @Override 497 public String toString() { 498 return org.opengion.fukurou.util.ToString.title( this.getClass().getName() ) 499 .println( "VERSION" ,VERSION ) 500 .println( "orderBy" ,orderBy ) 501 .println( "desc" ,desc ) 502 .println( "from" ,from ) 503 .println( "selValue" ,selValue ) 504 .println( "storageType" ,storageType) 505 .println( "bucketName" ,bucketName ) 506 .println( "storageType" ,storageType) 507 .println( "bucketName" ,bucketName ) 508 .println( "Other..." ,getAttributes().getAttribute() ) 509 .fixForm().toString() ; 510 } 511}