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?šあã‚?EVAL_BODY_BUFFERED:BODYを評価しã?{@XXXX} を解析しまã�?
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    }