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             */
417            private void writeObject( final ObjectOutputStream strm ) throws IOException {
418                    strm.defaultWriteObject();
419            }
420    
421            /**
422             * シリアライズ用のカスタ?リアライズ読み込みメソ?
423             *
424             * ここでは、transient 宣?れた?変数の??初期化が?なフィールド?み設定します?
425             *
426             * @og.rev 4.0.0.0 (2006/09/31) 新規追?
427             * @serialData
428             *
429             * @param       strm    ObjectInputStreamオブジェク?
430             * @see #release2()
431             */
432            private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException {
433                    strm.defaultReadObject();
434            }
435    
436            /**
437             * こ?オブジェクト???表現を返します?
438             * 基本???目?使用します?
439             *
440             * @return こ?クラスの??表現
441             */
442            @Override
443            public String toString() {
444                    return org.opengion.fukurou.util.ToString.title( this.getClass().getName() )
445                                    .println( "VERSION"             ,VERSION        )
446                                    .println( "orderBy"             ,orderBy        )
447                                    .println( "desc"                ,desc           )
448                                    .println( "from"                ,from           )
449                                    .println( "selValue"    ,selValue       )
450                                    .println( "Other..."    ,getAttributes().getAttribute() )
451                                    .fixForm().toString() ;
452            }
453    }