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