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                    OptionAncestorIF select = (OptionAncestorIF)findAncestorWithClass( this, OptionAncestorIF.class );
116                    if( select == null ) {
117    //                      String errMsg = "こã?タグは、SelectTag のBODY に記述するå¿?¦�がありますã?";
118                            String errMsg = "<b>" + getTagName() + "タグは、SelectTag またã?、DatalistTag のBODY に記述するå¿?¦�がありますã?</b>";
119                            throw new HybsSystemException( errMsg );
120                    }
121                    Comparator<File> comp = makeComparator( orderBy,desc );
122                    makeLabel( select,comp );
123    
124                    return(EVAL_PAGE);
125            }
126    
127            /**
128             * タグリブオブジェクトをリリースしますã?
129             * キャãƒ?‚·ュされて再利用されるã?で、フィールドã?初期設定を行いますã?
130             *
131             * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応ã?release2() ã‚?doEndTag()で呼ぶã€?
132             *
133             */
134            @Override
135            protected void release2() {
136                    super.release2();
137                    orderBy         = null;         // ?¿?°???目
138                    desc            = false;        // 降é??Œラク??
139                    from            = HybsSystem.sys( "FILE_URL" );
140                    filter          = null;
141                    selValue        = null;
142            }
143    
144            /**
145             * オプションを作æ?しますã?
146             *
147             * ファイル名を "value" にã€?
148             * BODY属æ? に登録するOptionを作æ?しますã?
149             *
150             * @og.rev 5.3.4.0 (2011/04/01) FILE_LENGTH 追åŠ?
151             *
152             * @param       orderBy ソートする属æ?[NAME/LASTMODIFIED/FILE_LENGTH/LENGTH]
153             * @param       desc    並びé ?true:æ˜??/false:降é?]
154             *
155             * @return      ファイル比è¼?”¨のComparatorオブジェクãƒ?
156             */
157            private Comparator<File> makeComparator( final String orderBy,final boolean desc ) {
158                    if( orderBy == null ) { return null; }
159    
160                    Comparator<File> comp = null ;
161    
162                    if( "NAME".equalsIgnoreCase( orderBy ) ) {
163                            comp = new NameComparator( desc );
164                    }
165                    else if( "LASTMODIFIED".equalsIgnoreCase( orderBy ) ) {
166                            comp = new ModifiedComparator( desc );
167                    }
168                    // "LENGTH" を残すのは、互換性のため
169                    else if( "FILE_LENGTH".equalsIgnoreCase( orderBy ) || "LENGTH".equalsIgnoreCase( orderBy ) ) {
170                            comp = new LengthComparator( desc );
171                    }
172    
173                    return comp ;
174            }
175    
176            /**
177             * オプションを作æ?しますã?
178             *
179             * ?Œァ?²?™名ã‚?"value" にã€?
180             * BODY属æ? に登録するOptionを作æ?しますã?
181             *
182             * @og.rev 3.8.0.9 (2005/10/17) è¤?•°選択可能時に全選択を設定するã?
183             *
184             * @param       select  SelectTagオブジェクãƒ?
185             * @param       comp    並びé ?‚’æŒ?®šするためã?Comparatorオブジェクãƒ?
186             */
187    //      private void makeLabel( final SelectTag select,final Comparator<File> comp ) {
188            private void makeLabel( final OptionAncestorIF select,final Comparator<File> comp ) {
189                    File path = new File( from );
190    
191                    File[] list = path.listFiles( filter );
192    
193                    boolean multipleAll = select.isMultipleAll();           // 3.8.0.9 (2005/10/17)
194                    if( list != null )  {
195                            Arrays.sort( list, comp );
196                            for( int i = 0; i < list.length; i++ ) {
197                                    if( list[i].isDirectory() ) { continue; }       // ãƒ?‚£レクトリは除å¤?
198                                    Attributes attri = new Attributes();
199                                    String value = list[i].getName();
200                                    attri.set( "value", value );
201                                    if( ( selValue != null && selValue.equalsIgnoreCase( value ) ) || multipleAll ) {
202                                            attri.set( "selected", "selected" );
203                                    }
204                                    attri.set( "body", value );
205                                    select.addOption( XHTMLTag.option( attri ) );
206                            }
207                    }
208            }
209    
210            /**
211             * 【TAG】Optionの初期値で選ばれる値を指定しますã?
212             *
213             * @og.tag
214             * キーになるã?は、ファイル属æ?の NAME ですã?(ãƒ?‚£レクトリなしã?ファイルå�?
215             * ここで value属æ?にæŒ?®šしたå?合ã?こã?ファイル名と(大æ–?­—小文字を無視して)
216             * ä¸??する場合に、ã?ルãƒ?‚¦ンの初期値に表示されますã?(selected 属æ?が設定されるã€?
217             *
218             * @param   val  初期値で選ばれる値
219             */
220            public void setValue( final String val ) {
221                    selValue = nval( getRequestParameter( val ),selValue );
222            }
223    
224            /**
225             * 【TAG】ファイルの検索å…?�¨なるディレクトリを指定しまã�?
226             *              (初期値:FILE_URL[={@og.value org.opengion.hayabusa.common.SystemData#FILE_URL}])ã€?
227             *
228             * @og.tag ファイルの検索å…?�¨なるディレクトリを指定しますã?
229             * (初期値:シスãƒ?ƒ 定数のFILE_URL[={@og.value org.opengion.hayabusa.common.SystemData#FILE_URL}])ã€?
230             *
231             * @og.rev 4.0.0.0 (2007/11/20) æŒ?®šされたãƒ?‚£レクトリ名ã?æœ?¾Œが"\"or"/"で終わってã�?�ªã�??合にã€?/"を付加するã€?
232             *
233             * @param       url ファイルの検索å…?�¨なるディレクトリ
234             * @see         org.opengion.hayabusa.common.SystemData#FILE_URL
235             */
236            public void setFrom( final String url ) {
237                    String furl = nval( getRequestParameter( url ),null );
238                    if( furl != null ) {
239                            char ch = furl.charAt( furl.length()-1 );
240                            if( ch != '/' && ch != '\\' ) { furl = furl + "/"; }
241                    }
242                    furl = StringUtil.urlAppend( from,furl );
243                    furl = StringUtil.urlAppend( furl,"." );
244                    from = HybsSystem.url2dir( furl );
245            }
246    
247            /**
248             * 【TAG】検索した結果を表示する表示é ?‚’ファイル属æ?名でæŒ?®šしまã�?初期値:自然é ?º?ã€?
249             *
250             * @og.tag
251             * ファイルをソートするé?(Comparator)を指定しますã?ソートにæŒ?®šできる
252             * ファイル属æ?名ã?ã€?NAME","LASTMODIFIED","FILE_LENGTH" のå†??どれかひとつですã?
253             * 何もæŒ?®šしなã�??合ã?、Fileオブジェクトã?自然é ?º�でのソートになりますã?
254             * (※ 下位互換性のため、LENGTH も残しますが、å»?­¢予定ですã?)
255             *
256             * @og.rev 3.5.6.2 (2004/07/05) æ–?­—å?の連結にStringBuilderを使用しますã?
257             * @og.rev 4.0.0.0 (2005/01/31) 新規ロジãƒ?‚¯で改å®?
258             * @og.rev 5.3.4.0 (2011/04/01) ORDER_BYリストã?出力方æ³?見直ã�?
259             *
260             * @param       ordr  ソートキー("NAME","LASTMODIFIED","FILE_LENGTH")
261             */
262            public void setOrderBy( final String ordr ) {
263                    orderBy = nval( getRequestParameter( ordr ),orderBy );
264    
265                    if( orderBy != null && ! check( orderBy, ORDER_BY ) ) {
266                            StringBuilder errMsg = new StringBuilder();
267                            errMsg.append( "orderBy 属æ?に、下記ã?属æ?名以外ã?値が設定されましたã€? );
268                            errMsg.append( HybsSystem.CR );
269                            errMsg.append( " orderBy=[" ).append( orderBy ).append( "]" );
270                            errMsg.append( HybsSystem.CR );
271                            errMsg.append( " orderBy List=[" );
272                            errMsg.append( StringUtil.array2csv( ORDER_BY ) );
273                            errMsg.append( "]" );
274    //                      for( int i=0; i<ORDER_BY.length; i++ ) {
275    //                              errMsg.append( ORDER_BY[i] );
276    //                              if( i == ORDER_BY.length-1 ) { errMsg.append( "]" ); }
277    //                              else {                                             errMsg.append( "," ); }
278    //                      }
279                            throw new HybsSystemException( errMsg.toString() );
280                    }
281            }
282    
283            /**
284             * 【TAG】表示é ?‚’é€?»¢するかどã�?�‹[true/false]を指定しまã�?初期値:false)ã€?
285             *
286             * @og.tag
287             * orderBy 属æ?でæŒ?®šした表示é ?‚’ã€??é ?�«するかどã�?�‹を指定できますã?
288             * 初期値は、false (æ˜??) ですã?
289             *
290             * @param       flag 表示é ?‚’é€?»¢するかどã�?�‹ [true:é€??/false:æ˜??]
291             */
292            public void setDesc( final String flag ) {
293                    desc = nval( getRequestParameter( flag ),desc );
294            }
295    
296            /**
297             * FileFilterオブジェクトをセãƒ?ƒˆしますã?
298             * これは、BODY 部に登録した、FileWhereタグによって設定された
299             * ファイルフィルターですã?
300             *
301             * @param       filter  オブジェクãƒ?
302             */
303            protected void setFileFilter( final FileFilter filter ) {
304                    this.filter = filter;
305            }
306    
307            /**
308             * 名前é ?�§のソートé?を指定すã‚?Comparator の実体å?部クラス
309             *
310             * @og.group そã?他å?åŠ?
311             *
312             * @version  4.0
313             * @author   Kazuhiko Hasegawa
314             * @since    JDK5.0,
315             */
316            static class NameComparator implements Comparator<File>,Serializable {
317                    private static final long serialVersionUID = 4000 ;
318    
319                    private final boolean desc ;
320    
321                    /**
322                     * 名前é ?�§の比è¼?‚’行うオブジェクトを作æ?しますã?
323                     *
324                     * @param desc [true:æ˜??/false:降é?]
325                     */
326                    public NameComparator( final boolean desc ) { this.desc = desc; }
327    
328                    /**
329                     * Comparator インターフェースの compare( File,File ) メソãƒ?ƒ‰
330                     *
331                     * @param o1 File 比è¼???‘ã?ファイルオブジェクãƒ?
332                     * @param o2 File 比è¼???’ã?ファイルオブジェクãƒ?
333                     */
334                    public int compare( final File o1, final File o2 ) {
335                            File f1 = (desc) ? o2 : o1 ;
336                            File f2 = (desc) ? o1 : o2 ;
337                            return (f1.getName()).compareTo( f2.getName() ) ;
338                    }
339            }
340    
341            /**
342             * 更新日é ?�§のソートé?を指定すã‚?Comparator の実体å?部クラス
343             *
344             * @og.group そã?他å?åŠ?
345             *
346             * @version  4.0
347             * @author   Kazuhiko Hasegawa
348             * @since    JDK5.0,
349             */
350            static class ModifiedComparator implements Comparator<File>,Serializable {
351                    private static final long serialVersionUID = 4000 ;
352    
353                    private final boolean desc ;
354    
355                    /**
356                     * 更新日é ?�§の比è¼?‚’行うオブジェクトを作æ?しますã?
357                     *
358                     * @param desc [true:æ˜??/false:降é?]
359                     */
360                    public ModifiedComparator( final boolean desc ) { this.desc = desc; }
361    
362                    /**
363                     * Comparator インターフェースの compare( File,File ) メソãƒ?ƒ‰
364                     *
365                     * @param o1 File 比è¼???‘ã?ファイルオブジェクãƒ?
366                     * @param o2 File 比è¼???’ã?ファイルオブジェクãƒ?
367                     */
368                    public int compare( final File o1, final File o2 ) {
369                            File f1 = (desc) ? o2 : o1 ;
370                            File f2 = (desc) ? o1 : o2 ;
371                            return (int)( f1.lastModified() - f2.lastModified() ) ;
372                    }
373            }
374    
375            /**
376             * ファイルサイズé ?�§のソートé?を指定すã‚?Comparator の実体å?部クラス
377             *
378             * @og.group そã?他å?åŠ?
379             *
380             * @version  4.0
381             * @author   Kazuhiko Hasegawa
382             * @since    JDK5.0,
383             */
384            static class LengthComparator implements Comparator<File>,Serializable {
385                    private static final long serialVersionUID = 4000 ;
386    
387                    private final boolean desc ;
388    
389                    /**
390                     * ファイルサイズでの比è¼?‚’行うオブジェクトを作æ?しますã?
391                     *
392                     * @param desc [true:æ˜??/false:降é?]
393                     */
394                    public LengthComparator( final boolean desc ) { this.desc = desc; }
395    
396                    /**
397                     * Comparator インターフェースの compare( File,File ) メソãƒ?ƒ‰
398                     *
399                     * @param o1 File 比è¼???‘ã?ファイルオブジェクãƒ?
400                     * @param o2 File 比è¼???’ã?ファイルオブジェクãƒ?
401                     */
402                    public int compare( final File o1, final File o2 ) {
403                            File f1 = (desc) ? o2 : o1 ;
404                            File f2 = (desc) ? o1 : o2 ;
405                            return (int)( f1.length() - f2.length() ) ;
406                    }
407            }
408    
409            /**
410             * シリアライズ用のカスタãƒ?‚·リアライズ書き込みメソãƒ?ƒ‰
411             *
412             * @og.rev 4.0.0.0 (2006/09/31) 新規追åŠ?
413             * @serialData ä¸?ƒ¨のオブジェクトã?、シリアライズされませんã€?
414             *
415             * @param       strm    ObjectOutputStreamオブジェクãƒ?
416             * @throws IOException  シリアライズに関する入出力エラーが発生したå?å�?
417             */
418            private void writeObject( final ObjectOutputStream strm ) throws IOException {
419                    strm.defaultWriteObject();
420            }
421    
422            /**
423             * シリアライズ用のカスタãƒ?‚·リアライズ読み込みメソãƒ?ƒ‰
424             *
425             * ここでは、transient 宣è¨?�•れたå†?ƒ¨変数のå†??初期化がå¿?¦�なフィールドã?み設定しますã?
426             *
427             * @og.rev 4.0.0.0 (2006/09/31) 新規追åŠ?
428             * @serialData ä¸?ƒ¨のオブジェクトã?、シリアライズされませんã€?
429             *
430             * @param       strm    ObjectInputStreamオブジェクãƒ?
431             * @see #release2()
432             * @throws IOException  シリアライズに関する入出力エラーが発生したå?å�?
433             * @throws ClassNotFoundException       クラスを見つけることができなかったå?å�?
434             */
435            private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException {
436                    strm.defaultReadObject();
437            }
438    
439            /**
440             * こã?オブジェクトã?æ–?­—å?表現を返しますã?
441             * 基本çš?�«ãƒ?ƒ�ãƒ?‚°目çš?�«使用しますã?
442             *
443             * @return こã?クラスのæ–?­—å?表現
444             */
445            @Override
446            public String toString() {
447                    return org.opengion.fukurou.util.ToString.title( this.getClass().getName() )
448                                    .println( "VERSION"             ,VERSION        )
449                                    .println( "orderBy"             ,orderBy        )
450                                    .println( "desc"                ,desc           )
451                                    .println( "from"                ,from           )
452                                    .println( "selValue"    ,selValue       )
453                                    .println( "Other..."    ,getAttributes().getAttribute() )
454                                    .fixForm().toString() ;
455            }
456    }