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.util.Arrays;
026
027import org.opengion.fukurou.security.HybsCryptography ;         // 5.7.4.3 (2014/03/28)
028import org.opengion.fukurou.util.StringUtil;
029import org.opengion.hayabusa.common.HybsSystem;
030import org.opengion.hayabusa.common.HybsSystemException;
031import org.opengion.hayabusa.db.DBColumn;
032import org.opengion.hayabusa.db.DBTableModel;
033import org.opengion.hayabusa.db.DBTableModelSorter;
034import org.opengion.hayabusa.db.DBTableModelUtil;
035import org.opengion.hayabusa.io.HybsFileOperationFactory;
036
037/**
038 * ファイルを検索し、DBTableModel にセットするタグです。
039 *
040 * ファイルの検索結果は、[WRITABLE],LEVEL,FILE_TYPE,PARENT,NAME,LASTMODIFIED,FILE_LENGTH,RWH,[MD5],[TO_PARENT,TO_NAME],[・・・・]
041 * のカラムを持つ DBTableModel にセット されます。このカラムは、固定です。
042 * 並び替えについては、このタグで指定しますが、ファイルの選別(where 条件)は、
043 * BODY 部に記述する fileWhere タグで指定します。(複数指定可能))
044 *
045 * [カラム名]      検索するファイルの属性は、以下のカラム名で作成されます。
046 *     [WRITABLE]       useWritable=trueで、先頭カラムに、WRITABLE カラムが挿入されます。
047 *      LEVEL           ディレクトリを展開する場合のレベル。
048 *      FILE_TYPE       ファイル(F)かディレクトリ(D)であるか判定。
049 *      PARENT          この抽象パス名の親のパス名文字列を返します。
050 *      NAME            この抽象パス名が示すファイルまたはディレクトリの名前を返します。
051 *      LASTMODIFIED    最後に変更された時刻を返します。
052 *      FILE_LENGTH     ファイルの長さを返します。
053 *      RWH             読み込み、書き込み、隠し属性をそれぞれ、r,w,h で表します。
054 *     [MD5]            useMD5=trueで、MD5 というカラムを追加したうえで、ファイルのMD5計算を行います。
055 *     [TO_PARENT]      useUpdateClms=trueで、fileUpdateタグでCOPYやMOVEを行う時に使用する必須となるカラム(TO_PARENT,TO_NAME)を追加します。
056 *     [TO_NAME]        同上
057 *     [・・・・]           addClms属性で指定されたカラムを追加します。
058 *
059 * @og.formSample
060 * ●形式:<og:fileQuery from="…" multi="true/false" >
061 *             <og:fileWhere … />
062 *              …
063 *         </og:fileQuery>
064 * ●body:あり(EVAL_BODY_BUFFERED:BODYを評価し、{@XXXX} を解析します)
065 *
066 * ●Tag定義:
067 *   <og:fileQuery
068 *       from             ○【TAG】検索を開始するファイルまたはディレクトリを指定します(必須)。
069 *       multi              【TAG】多段階展開するか、1レベル展開するかどうか[true:多段階/false:1レベル]を指定します(初期値:false:1レベル)。
070 *       level              【TAG】多段階展開するレベルを指定します(初期値:100)。
071 *       orderBy            【TAG】ソートするカラム名を指定します(一つのみ)。
072 *       desc               【TAG】表示順を逆転するかどうか[true/false]を指定します(初期値:false)。
073 *       useWritable        【TAG】先頭カラムに、WRITABLE カラムを追加するかどうか[true/false]を指定します(初期値:false)。
074 *       useMD5             【TAG】MD5カラムを追加したうえで、MD5計算を行うかどうか[true/false]を指定します(初期値:false)。
075 *       useUpdateClms      【TAG】TO_PARENT、TO_NAMEカラムを追加するかどうか[true/false]を指定します(初期値:false)。
076 *       addClms            【TAG】検索結果のカラム列に追加するカラム名を、カンマ区切り文字で指定します。
077 *       fileType           【TAG】選択対象[FILE/DIR]を指定します。下位展開は考慮(multi 属性準拠)されます。
078 *       addFrom            【TAG】from属性で指定された基準ファイル/フォルダ自体をリストに追加するかどうか[true/false]を指定します(初期値:true)。
079 *       command            【TAG】コマンド(NEW,RENEW)をセットします("NEW" と "RENEW" 時のみ実行する(初期値:NEW))。
080 *       maxRowCount        【TAG】(通常は使いません)データの最大読み込み件数を指定します (初期値:DB_MAX_ROW_COUNT[=1000])(0:[無制限])。
081 *       displayMsg         【TAG】検索結果を画面上に表示するメッセージリソースIDを指定します (初期値:VIEW_DISPLAY_MSG[=])v
082 *       overflowMsg        【TAG】検索データが最大検索数をオーバーした場合に表示するメッセージリソースIDを指定します (初期値:MSG0007[検索結果が、制限行数を超えましたので、残りはカットされました])。
083 *       notfoundMsg        【TAG】検索結果がゼロ件の場合に表示するメッセージリソースIDを指定します(初期値:MSG0077[対象データはありませんでした])。
084 *       tableId            【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します
085 *       scope              【TAG】キャッシュする場合のスコープ[request/page/session/applicaton]を指定します(初期値:session)。
086 *       storageType            【TAG】読み取り元ストレージタイプを指定します(初期値:CLOUD_TARGET)
087 *       bucketName                     【TAG】読み取り元バケット名を指定します(初期値:CLOUD_BUCKET)
088 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)。
089 *   >   ... Body ...
090 *   </og:fileQuery>
091 *
092 * ●使用例
093 *    ・一般的な属性でファイルの検索を行います。
094 *         <og:fileQuery
095 *                from    = "d:/webapps/dbdef/jsp/"
096 *                multi   = "true"
097 *                command = "{@command}"  >
098 *            <og:fileWhere endWith=".jsp" />
099 *      </og:fileQuery>
100 *
101 *    ・最終変更日で逆順ソートする。対象は、2002/10/01 以降に変更されたファイル。
102 *        <og:fileQuery
103 *                from    = "d:/webapps/dbdef/jsp/"
104 *                multi   = "true"
105 *                orderBy = "LASTMODIFIED"
106 *                desc    = "true"
107 *                command = "{@command}"  >
108 *            <og:fileWhere lastModified="20021001000000" />
109 *        </og:fileQuery>
110 *
111 * @og.rev 4.0.0.0 (2005/01/31) 内部ロジック改定
112 * @og.rev 5.10.9.0 (2019/03/01) oota クラウドストレージ対応を追加。(Fileクラスを拡張)
113 * 
114 * @og.group その他入力
115 *
116 * @version  4.0
117 * @author       Kazuhiko Hasegawa
118 * @since    JDK5.0,
119 */
120public class FileQueryTag extends QueryTag {
121        //* このプログラムのVERSION文字列を設定します。   {@value} */
122        private static final String VERSION = "5.7.4.3 (2014/03/28)" ;
123
124        private static final long serialVersionUID = 574320140328L ;
125
126        private static final String[] SELECT =
127                                new String[] { "LEVEL","FILE_TYPE","PARENT","NAME","LASTMODIFIED","FILE_LENGTH","RWH" };
128
129        // 5.7.4.3 (2014/03/28) WRITABLE 対応のため、固定アドレスを止めます。
130//      private static final int LEVEL                  = 0;
131//      private static final int FILE_TYPE              = 1;
132//      private static final int PARENT                 = 2;
133//      private static final int NAME                   = 3;
134//      private static final int LASTMODIFIED   = 4;
135//      private static final int FILE_LENGTH    = 5;
136//      private static final int RWH                    = 6;
137
138        private static final String[] USE_UPDATE_CLM = new String[] { "TO_PARENT","TO_NAME" };  // 5.3.4.0 (2011/04/01)
139
140        private transient FileFilter filter     = null;                                                 // FileWhere で指定したフィルター
141        
142        private boolean         multi                   = false;                                                // 下位層展開フラグ
143        private int                     level                   = 100;                                                  // 展開レベル
144        private String      from                        = HybsSystem.sys( "FILE_URL" ); // 検索起点ファイル
145        private String          orderBy                 = null;                                                 // 5.3.4.0 (2011/04/01) ソートカラム
146        private boolean         desc                    = false;                                                // 5.3.4.0 (2011/04/01) ソートの方向(true:逆順)
147        private String[]        addClms                 = new String[0];                                // 5.3.4.0 (2011/04/01) 追加カラム配列
148//      private String[]        valClms                 = null;                                                 // 5.3.4.0 (2011/04/01) 追加カラム配列の初期値
149        private String[]        defClms                 = null;                                                 // 5.7.4.3 (2014/03/28) 初期値のカラム配列
150        private String          fileType                = null;                                                 // 5.3.4.0 (2011/04/01) 選択対象を指定(FILE,DIR)
151        private boolean         useWritable             = false;                                                // 5.7.4.3 (2014/03/28) 先頭カラムに、WRITABLE カラムを追加するかどうか[true/false](初期値:false)
152        private boolean         useMD5                  = false;                                                // 5.7.4.3 (2014/03/28) MD5カラムを追加したうえで、MD5計算を行うかどうか[true/false](初期値:false)
153        private boolean         useUpdateClms   = false;                                                // 5.3.4.0 (2011/04/01) TO_PARENT、TO_NAMEカラムを追加(true:追加)
154        private boolean         addFrom                 = true;                                                 // 5.3.9.0 (2011/09/01) from属性で指定された基準ファイル/フォルダ自体をリストに追加するかどうか
155        private String          storageType             = null;                                                 // 5.10.9.0 (2019/03/01) クラウドストレージタイプ
156        private String          bucketName              = null;                                                 // 5.10.9.0 (2019/03/01) バケット名
157        
158        /**
159         * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。
160         *
161         * @og.rev 5.3.4.0 (2011/04/01) 指定カラムのソート処理機能追加
162         * @og.rev 5.3.5.0 (2011/05/01) 最初のファイルが存在する場合のみ、実行する。
163         * @og.rev 5.10.9.0 (2019/03/01) クラウドストレージ対応。
164         *
165         * @return      後続処理の指示(SKIP_BODY)
166         */
167        @Override
168        public int doAfterBody() {
169                executeCount = 0;
170
171                table = initDBTable();
172                if( maxRowCount < 0 ) {
173                        maxRowCount     = sysInt( "DB_MAX_ROW_COUNT" ) ;
174                }
175
176//              execute( new File( from ),0 ) ; // 5.3.5.0 (2011/05/01) 廃止
177
178                // 5.3.5.0 (2011/05/01) 最初のファイルが存在する場合のみ、実行する。
179                // 5.10.9.0 (2019/03/01) MODIFY
180//              File fin = new File( from );
181                File fin = HybsFileOperationFactory.create(storageType, bucketName, from);
182                if( fin.exists() ) {
183                        execute( fin,0 ) ;
184
185                        // 5.3.4.0 (2011/04/01) 指定カラムのソート処理
186                        if( orderBy != null ) {
187                                int clmNo = table.getColumnNo( orderBy );
188                                DBTableModelSorter temp = new DBTableModelSorter();
189                                temp.setModel( table );
190                                temp.sortByColumn( clmNo,!desc );       // 注意 desc の値と ソート正逆は、反対です。
191                                table = temp;
192                        }
193                }
194
195                return(SKIP_BODY);
196        }
197
198        /**
199         * タグリブオブジェクトをリリースします。
200         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
201         *
202         * @og.rev 5.3.4.0 (2011/04/01) 指定カラムのソート処理機能、カラム追加機能、fileType追加
203         * @og.rev 5.3.9.0 (2011/09/01) addFrom属性追加
204         * @og.rev 5.7.4.3 (2014/03/28) useWritable,useMD5属性追加。valClms を defClms に置き換え。
205         * @og.rev 5.10.9.0 (2019/03/01) storageType,bucketName属性を追加。
206         */
207        @Override
208        protected void release2() {
209                super.release2();
210                multi                   = false;
211                level                   = 100;
212                from                    = HybsSystem.sys( "FILE_URL" );
213                filter                  = null;
214                orderBy                 = null;                         // 5.3.4.0 (2011/04/01) ソートカラム
215                desc                    = false;                        // 5.3.4.0 (2011/04/01) 降順フラグ
216                addClms                 = new String[0];        // 5.3.4.0 (2011/04/01) 追加カラム配列
217//              valClms                 = null;                         // 5.3.4.0 (2011/04/01) 追加カラム配列の初期値
218                defClms                 = null;                         // 5.7.4.3 (2014/03/28) 初期値のカラム配列
219                fileType                = null;                         // 5.3.4.0 (2011/04/01) 選択対象を指定(FILE,DIR,ALL)
220                useWritable             = false;                        // 5.7.4.3 (2014/03/28) 先頭カラムに、WRITABLE カラムを追加するかどうか[true/false](初期値:false)
221                useMD5                  = false;                        // 5.7.4.3 (2014/03/28) MD5カラムを追加したうえで、MD5計算を行うかどうか[true/false](初期値:false)
222                useUpdateClms   = false;                        // 5.3.4.0 (2011/04/01) TO_PARENT、TO_NAMEカラムを追加(true:追加)
223                addFrom                 = true;                         // 5.3.9.0 (2011/09/01) addFrom属性追加
224                storageType             = null;                         // 5.10.9.0 (2019/03/01) 読み取り元ストレージタイプ
225                bucketName              = null;                         // 5.10.9.0 (2019/03/01) 読み取り元バケット名
226        }
227
228        /**
229         * FileQuery を実行します。
230         *
231         * @og.rev 5.3.4.0 (2011/04/01) fileType の条件に合致する場合だけ、データを作成する。
232         * @og.rev 5.3.7.0 (2011/07/01) フォルダにアクセスできない場合は、null となるのでその対応
233         * @og.rev 5.3.9.0 (2011/09/01) addFrom属性追加
234         *
235         * @param       fin     検索を開始するファイル/ディレクトリ
236         * @param       lvl     階層展開レベル
237         */
238        protected void execute( final File fin,final int lvl ) {
239                if( ( !multi && lvl > 1 ) || lvl > level ) { return; }    // 階層展開する、しない
240                if( executeCount > maxRowCount ) { table.setOverflow( true ); return; }
241
242                boolean isDIR = fin.isDirectory();
243
244                if( fileType == null ||
245                        (  isDIR &&  "DIR".equalsIgnoreCase( fileType ) ) ||
246                        ( !isDIR && "FILE".equalsIgnoreCase( fileType ) ) ) {
247                                if( addFrom || ( !addFrom && lvl > 0 ) ) {
248                                        addFileData( executeCount++,lvl,fin );
249                                }
250                }
251                
252//              if( fin.isDirectory() ) {
253                if( isDIR ) {
254                        File[] list = fin.listFiles( filter );
255                        // 5.3.7.0 (2011/07/01) フォルダにアクセスできない場合は、null となる。
256                        if( list != null ) {
257                                for( int i = 0; i < list.length; i++ ) {
258                                        execute( list[i],lvl+1 );
259                                }
260                        }
261                }
262        }
263
264        /**
265         * 初期化された DBTableModel を返します。
266         *
267         * ここでは、useWritable、useMD5、useUpdateClms、addClms を加味した
268         * DBTableModel と初期値データ(defClms)を作成します。
269         * 以前は、TO_PARENT、TO_NAMEと、addClms 分のみ初期値を持っていましたが、
270         * 5.7.4.3 (2014/03/28)で、先頭カラムのWRITABLEの初期値を、DBColumn の初期値ではなく
271         * 手動設定する必要がある為、すべてのカラム列の初期値を持っておきます。
272         *
273         * @og.rev 5.3.4.0 (2011/04/01) 指定カラム追加機能追加
274         * @og.rev 5.7.4.3 (2014/03/28) useWritable,useMD5属性追加
275         *
276         * @return       テーブルモデル
277         */
278        private DBTableModel initDBTable() {
279                DBTableModel tbl = DBTableModelUtil.newDBTable();
280
281                // 5.7.4.3 (2014/03/28) 以下の処理は、ほぼ全面見直し
282                int size = SELECT.length ;                                                              // 基本カラムの数
283                
284                if( useWritable   ) { size++ ; }                                                // WRITABLE カラムを追加
285                if( useMD5        ) { size++ ; }                                                // MD5 カラムを追加
286                if( useUpdateClms ) { size += USE_UPDATE_CLM.length; }  // TO_PARENT、TO_NAMEカラムを追加
287                size += addClms.length ;                                                                // addClms(追加カラム)数を追加
288
289                // DBTableModel の初期化と、初期値配列の確保
290                tbl.init( size );
291                defClms = new String[size];
292
293                int ad=0;
294                // 先頭は、WRITABLE
295                if( useWritable ) {
296                        DBColumn dbColumn = getDBColumn( "WRITABLE" );
297                        defClms[ad] = "1";                                                                      // WRITABLE を設定するときは、とりあえず 書き込み許可
298                        tbl.setDBColumn( ad++,dbColumn );
299                }
300
301                // SELECT の 基本カラムの設定。(初期値は不要)
302                for( int i=0; i<SELECT.length; i++ ) {
303                        DBColumn dbColumn = getDBColumn( SELECT[i] );
304                        tbl.setDBColumn( ad++,dbColumn );
305                }
306
307                // MD5 カラムを追加。
308                if( useMD5 ) {
309                        DBColumn dbColumn = getDBColumn( "MD5" );
310                        defClms[ad] = "";                                                                       // ディレクトリの場合は、MD5計算しません。
311                        tbl.setDBColumn( ad++,dbColumn );
312                }
313
314                // TO_PARENT、TO_NAMEカラムを追加
315                if( useUpdateClms ) {
316                        for( int i=0; i<USE_UPDATE_CLM.length; i++ ) {
317                                DBColumn dbColumn = getDBColumn( USE_UPDATE_CLM[i] );
318                                defClms[ad] = dbColumn.getDefault();                    // 初期値を指定しておく
319                                tbl.setDBColumn( ad++,dbColumn );
320                        }
321                }
322
323                // 追加カラムのaddClmsカラムを追加
324                for( int i=0; i<addClms.length; i++ ) {
325                        DBColumn dbColumn = getDBColumn( addClms[i] );
326                        defClms[ad] = dbColumn.getDefault();                                    // 初期値を指定しておく
327                        tbl.setDBColumn( ad++,dbColumn );
328                }
329
330                return tbl ;
331
332//              // TO_PARENT、TO_NAMEカラムを追加
333//              int clmSize = addClms.length ;
334//              if( useUpdateClms ) {
335//                      if( clmSize == 0 ) {
336//                              addClms = USE_UPDATE_CLM ;
337//                      }
338//                      else {
339//                              // 追加カラムが存在する場合は、加算します。
340//                              addClms = Arrays.copyOf( addClms ,clmSize + USE_UPDATE_CLM.length );    // JDK1.6
341//                              for( int i=0; i<USE_UPDATE_CLM.length; i++ ) {
342//                                      addClms[clmSize+i] = USE_UPDATE_CLM[i];
343//                              }
344//                      }
345//              }
346//              valClms = new String[addClms.length];
347//
348//              tbl.init( SELECT.length + addClms.length );
349//              int ad=0;
350//              for( int i=0; i<SELECT.length; i++ ) {
351//                      DBColumn dbColumn = getDBColumn( SELECT[i] );
352//                      tbl.setDBColumn( ad++,dbColumn );
353//              }
354//
355//              for( int i=0; i<addClms.length; i++ ) {
356//                      DBColumn dbColumn = getDBColumn( addClms[i] );
357//                      valClms[i] = dbColumn.getDefault();                             // 初期値を指定しておく
358//                      tbl.setDBColumn( ad++,dbColumn );
359//              }
360//
361//              return tbl ;
362        }
363        
364        /**
365         * DBTableModel に、ファイル情報をセットします。
366         * ファイル情報は、[WRITABLE],LEVEL,FILE_TYPE,PARENT,NAME,LASTMODIFIED,FILE_LENGTH,RWH,[MD5],[TO_PARENT,TO_NAME],[・・・・] です。
367         *
368         * useWritable=true の場合、先頭カラムに、WRITABLE カラムを追加します。
369         * useMD5=true の場合、MD5カラムを追加したうえで、MD5計算を行います(ファイルのみ計算します)。
370         * useUpdateClms=true の場合TO_PARENT、TO_NAMEカラムを追加します。
371         * addClms で指定されたカラムをその後ろに追加します。
372         *
373         * @og.rev 5.3.4.0 (2011/04/01) 指定カラム追加機能追加
374         * @og.rev 5.7.4.3 (2014/03/28) useWritable,useMD5属性追加
375         *
376         * @param       rowNo   セットする行番号
377         * @param       lvl     セットするレベル
378         * @param       fin             ファイル情報の元となるファイルオブジェクト
379         */
380         private void addFileData( final int rowNo,final int lvl,final File fin ) {
381                try {
382                        File file = fin.getCanonicalFile();
383                        String rwh = ((file.canRead())?"r":"-" ) +
384                                                        ((file.canWrite())?"w":"-" ) +
385                                                        ((file.isHidden())?"h":"-" ) ;
386
387                        String lastModified = HybsSystem.getDate( file.lastModified(),"yyyyMMddHHmmss" );
388
389                        boolean isF = file.isFile();                                                            // File=true,それ以外=false
390
391                        int size = table.getColumnCount() ;
392//                      String[] data = new String[size];                                                       // 昔ながらの配列コピー
393//                      System.arraycopy( defClms, 0, data, 0, size );
394                        String[] data = Arrays.copyOf( defClms,size );                          // JDK1.6
395
396                        int ad=0;
397                        if( useWritable ) { ad++ ; }            // 単にひとつ進める。初期値はセット済み。
398
399                        // SELECT の 基本カラムの設定
400                        data[ad++] = String.valueOf( lvl ) ;                                            // LEVEL
401                        data[ad++] = (isF) ? "F" : "D" ;                                                        // FILE_TYPE
402                        data[ad++] = file.getParent() ;                                                         // PARENT
403                        data[ad++] = file.getName() ;                                                           // NAME
404                        data[ad++] = lastModified ;                                                                     // LASTMODIFIED
405                        data[ad++] = (isF) ? String.valueOf( file.length() ) : "" ;     // FILE_LENGTH
406                        data[ad++] = rwh ;                                                                                      // RWH
407
408                        // MD5 カラムを追加(ファイルの場合のみ計算します)
409                        if( useMD5 && isF ) {
410                                data[ad++] = HybsCryptography.getMD5( file );
411                        }
412
413                        // useUpdateClms=true 時の TO_PARENT、TO_NAMEカラムや、addClmsの追加カラムは、初期値のみセット
414                        // 初期値セットは、Arrays.copyOf で、defClms のコピーで完了。
415
416                        table.addColumnValues( data );
417
418//                      String[] data = new String[ SELECT.length + addClms.length ];   // 5.3.4.0 (2011/04/01) 指定カラム追加機能
419//                      data[LEVEL                      ] = String.valueOf( lvl ) ;
420//                      data[FILE_TYPE          ] = (file.isFile())?"F":"D" ;
421//                      data[PARENT                     ] = file.getParent() ;
422//                      data[NAME                       ] = file.getName() ;
423//                      data[LASTMODIFIED       ] = lastModified ;
424//                      data[FILE_LENGTH        ] = String.valueOf( file.length() ) ;
425//                      data[RWH                        ] = rwh ;
426//
427//                      // これ以降の data 配列には、カラムオブジェクトの初期値を設定しておく。
428//                      int ad = SELECT.length;
429//                      for( int i=0; i<addClms.length; i++ ) {
430//                              data[ad++] = valClms[i];
431//                      }
432
433//                      table.addColumnValues( data );
434                }
435                catch( IOException ex ) {
436                        String errMsg = "正式なファイル名の取得に失敗しました。[" + fin + "]"
437                                                + " ROW=[" + rowNo + "]"
438                                                + HybsSystem.CR + ex.getMessage();
439                        throw new HybsSystemException( errMsg,ex );
440                }
441        }
442
443        /**
444         * 【TAG】ファイルの検索元となるディレクトリを指定します。
445         *
446         * @og.tag ファイルの検索元となるディレクトリを指定します。
447         *
448         * @og.rev 4.0.0.0 (2007/11/20) 指定されたディレクトリ名の最後が"\"or"/"で終わっていない場合に、"/"を付加する。
449         *
450         * @param       url ファイルの検索元となるディレクトリ
451         */
452        public void setFrom( final String url ) {
453                String furl = nval( getRequestParameter( url ),null );
454                if( furl != null ) {
455                        char ch = furl.charAt( furl.length()-1 );
456                        if( ch != '/' && ch != '\\' ) { furl = furl + "/"; }
457                }
458                furl = StringUtil.urlAppend( from,furl );
459                furl = StringUtil.urlAppend( furl,"." );
460
461                from = HybsSystem.url2dir( furl );
462        }
463
464        /**
465         * 【TAG】多段階展開するか、1レベル展開するかどうか[true/false]を指定します(初期値:false)。
466         *
467         * @og.tag
468         * 初期値は、false (1レベル) です。
469         *
470         * @param       mlti 多段階展開するか [true:する/false:1レベル]
471         */
472        public void setMulti( final String mlti ) {
473                multi = nval( getRequestParameter( mlti ),multi );
474        }
475
476        /**
477         * 【TAG】多段階展開するレベルを指定します(初期値:100)。
478         *
479         * @og.tag
480         *
481         * @param       lvl 多段階展開するレベル
482         */
483        public void setLevel( final String lvl ) {
484                level = nval( getRequestParameter( lvl ),level );
485        }
486
487        /**
488         * 【TAG】ソートするカラム名を指定します(一つのみ)。
489         *
490         * @og.tag
491         * ソートするカラム名を、"LEVEL","FILE_TYPE","PARENT","NAME","LASTMODIFIED","FILE_LENGTH","RWH"
492         * から一つ選びます。
493         * これは、複数カラムでのソートはできません。
494         * 逆順にソートする場合は、desc属性を true にセットください。
495         * + をつけても、無効(カラム名がないということでエラーになります。
496         *
497         * @og.rev 5.3.4.0 (2011/04/01) 新規追加
498         *
499         * @param       clm ソートするカラム名(一つのみ)、逆順は、マイナスを付ける。
500         * @see         #setDesc( String )
501         */
502        public void setOrderBy( final String clm ) {
503                orderBy = nval( getRequestParameter( clm ),orderBy );
504
505                if( orderBy != null && ! check( orderBy, SELECT ) ) {
506                        String errMsg = "指定の orderBy は、指定できません。" + HybsSystem.CR
507                                                        + "orderBy=[" + orderBy + "] "   + HybsSystem.CR
508                                                        + StringUtil.array2csv( SELECT ) + HybsSystem.CR ;
509//                      throw new HybsSystemException( errMsg.toString() );
510                        throw new HybsSystemException( errMsg );
511                }
512        }
513
514        /**
515         * 【TAG】表示順を逆転するかどうか[true/false]を指定します(初期値:false)。
516         *
517         * @og.tag
518         * orderBy 属性で指定した表示順を、逆順にするかどうかを指定できます。
519         * 初期値は、false (昇順) です。
520         *
521         * @og.rev 5.3.4.0 (2011/04/01) 新規追加
522         *
523         * @param       flag 表示順を逆転するかどうか [逆順:true/正順:false]
524         * @see         #setOrderBy( String )
525         */
526        public void setDesc( final String flag ) {
527                desc = nval( getRequestParameter( flag ),desc );
528        }
529
530        /**
531         * 【TAG】先頭カラムに、WRITABLE カラムを追加するかどうか[true/false]を指定します(初期値:false)。
532         *
533         * @og.tag
534         * ファイル検索結果の1レコード単位に、書き込み許可/禁止属性を付けるには、
535         * カラム列の先頭に、WRITABLE カラムを追加する必要があります。
536         * 初期値は、false (追加しない) です。
537         *
538         * @og.rev 5.7.4.3 (2014/03/28) 新規追加
539         *
540         * @param       flag 先頭カラムに、WRITABLE カラムを追加するかどうか[true:追加する/false:追加しない]
541         */
542        public void setUseWritable( final String flag ) {
543                useWritable = nval( getRequestParameter( flag ),useWritable );
544        }
545
546        /**
547         * 【TAG】MD5カラムを追加したうえで、MD5計算を行うかどうか[true/false]を指定します(初期値:false)。
548         *
549         * @og.tag
550         * ファイルの改変等をチェックするには、ファイルのハッシュ値を拾う必要があります。
551         * タイムスタンプとサイズ(LASTMODIFIED,FILE_LENGTH)でも、類似の処理は可能ですが、
552         * より、厳密な一致をみるなら、MD5でハッシュした結果を突き合わせるのがベストです。
553         * useMD5=true に設定すると、MD5 というカラムを追加したうえで、MD5計算結果をセットします。
554         * 初期値は、false (追加しない) です。
555         *
556         * @og.rev 5.7.4.3 (2014/03/28) 新規追加
557         *
558         * @param       flag MD5カラムを追加したうえで、MD5計算を行うかどうか[true:追加する/false:追加しない]
559         */
560        public void setUseMD5( final String flag ) {
561                useMD5 = nval( getRequestParameter( flag ),useMD5 );
562        }
563
564        /**
565         * 【TAG】TO_PARENT、TO_NAMEカラムを追加するかどうか[true/false]を指定します(初期値:false)。
566         *
567         * @og.tag
568         * fileUpdateタグでは、ファイルのCOPYやMOVEが出来ますが、そのコピー先、移動先の
569         * ファイルを行ごとに指定する場合、TO_PARENT、TO_NAMEカラムという固定名のカラムが
570         * 必要です。
571         * これを、addClms 属性で指定する代わりに、この属性で、true をセットすることで、
572         * 自動的に追加されます。
573         * 初期値は、false (追加しない) です。
574         *
575         * @og.rev 5.3.4.0 (2011/04/01) 新規追加
576         *
577         * @param       flag TO_PARENT、TO_NAMEカラムを追加するかどうか [true:追加する/false:追加しない]
578         * @see         #setAddClms( String )
579         * @see         org.opengion.hayabusa.taglib.FileUpdateTag
580         */
581        public void setUseUpdateClms( final String flag ) {
582                useUpdateClms = nval( getRequestParameter( flag ),useUpdateClms );
583        }
584
585        /**
586         * 【TAG】検索結果のカラム列に追加するカラム名を、カンマ区切り文字で指定します。
587         *
588         * @og.tag
589         * デフォルトのカラム名、[WRITABLE],LEVEL,FILE_TYPE,PARENT,NAME,LASTMODIFIED,FILE_LENGTH,RWH,[MD5],[TO_PARENT,TO_NAME]
590         * 以外に、指定のカラム名を追加することが可能です。
591         * これは、ファイル検索結果以外の項目を追加して、データベースに書き込む場合に、利用できます。
592         * 並び順は、デフォルトカラムの後ろに、指定のカラムの順番で付きます。
593         * ここで追加したカラムには、カラムリソースの初期値がセットされます。
594         *
595         * @og.rev 5.3.4.0 (2011/04/01) 新規追加
596         *
597         * @param       clms 検索結果のカラム列に追加するカラム名を、カンマ区切り文字で指定します。
598         * @see         #setUseUpdateClms( String )
599         */
600        public void setAddClms( final String clms ) {
601                String tmpClms = nval( getRequestParameter( clms ),null );
602
603                if( tmpClms != null && tmpClms.length() > 0 ) {
604                        addClms = StringUtil.csv2Array( tmpClms );
605                }
606        }
607
608        /**
609         * 【TAG】ファイル名が、指定されたファイルタイプ[DIR/FILE]と一致した場合、スルー(選択)されます。
610         * @og.tag
611         * 大文字小文字は区別しません。
612         * ファイルタイプ は、DIR,FILE が指定できます。
613         * DIR は、ディレクトリのみ検索します。(階層下がりも行います)
614         * FILEは、ファイルのみ検索します。(階層下がりも行います)
615         * 引数が null の場合は、追加しません。(つまり、すべてスルーされます。)
616         *
617         * @og.rev 5.3.4.0 (2011/04/01) fileType メソッドで選択対象指定の追加
618         *
619         * @param    str 指定するファイルタイプ(DIR,FILE,null)
620         */
621        public void setFileType( final String str ) {
622                String tmp = nval( getRequestParameter( str ),fileType );
623                if( tmp == null                                         ||
624                        "DIR".equalsIgnoreCase( tmp )   ||
625                        "FILE".equalsIgnoreCase( tmp ) ) {
626                                fileType = tmp;
627                }
628                else {
629                        // ファイルタイプに不正な値が設定された場合は、エラーになる。
630                        String errMsg = "この、fileType 属性には、DIR,FILE 以外は指定できません。["
631                                                + tmp + "]";
632                        throw new HybsSystemException( errMsg );
633                }
634        }
635
636        /**
637         * 【TAG】from属性で指定された基準ファイル/フォルダ自体をリストに追加するかどうか[true/false]を指定します(初期値:true)。
638         * @og.tag
639         * 初期値はtrue(追加する)です。
640         *
641         * @og.rev 5.3.9.0 (2011/09/01) 新規作成
642         *
643         * @param    flg 基準ファイル/フォルダ自体をリストに追加するかどうか true:追加する/false:追加しない]
644         */
645        public void setAddFrom( final String flg ) {
646                addFrom = nval( getRequestParameter( flg ),addFrom );
647        }
648
649        /**
650         * FileFilterオブジェクトをセットします。
651         * これは、BODY 部に登録した、FileWhereタグによって設定された
652         * ファイルフィルターです。
653         * @param       filter  オブジェクト
654         */
655        protected void setFileFilter( final FileFilter filter ) {
656                this.filter = filter;
657        }
658
659        /**
660         * シリアライズ用のカスタムシリアライズ書き込みメソッド
661         *
662         * @og.rev 4.0.0.0 (2006/09/31) 新規追加
663         * @serialData 一部のオブジェクトは、シリアライズされません。
664         *
665         * @param       strm    ObjectOutputStreamオブジェクト
666         * @throws IOException  シリアライズに関する入出力エラーが発生した場合
667         */
668        private void writeObject( final ObjectOutputStream strm ) throws IOException {
669                strm.defaultWriteObject();
670        }
671
672        /**
673         * シリアライズ用のカスタムシリアライズ読み込みメソッド
674         *
675         * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。
676         *
677         * @og.rev 4.0.0.0 (2006/09/31) 新規追加
678         * @serialData 一部のオブジェクトは、シリアライズされません。
679         *
680         * @param       strm    ObjectInputStreamオブジェクト
681         * @see #release2()
682         * @throws IOException  シリアライズに関する入出力エラーが発生した場合
683         * @throws ClassNotFoundException       クラスを見つけることができなかった場合
684         */
685        private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException {
686                strm.defaultReadObject();
687        }
688
689        /**
690         * 【TAG】読み取り元ストレージタイプを設定します。
691         *  
692         * @og.tag
693         * ファイルを読み取り元の、ストレージタイプを設定します。
694         * 未設定の場合は、システムリソースの「CLOUD_TARGET」が参照されます。
695         * 自身のサーバを指定する場合は、「default」を設定してください。
696         * 
697         * @og.rev 5.10.9.0 (2019/03/01) 新規追加
698         * 
699         * @param storage ストレージタイプ
700         */
701        public void setStorageType( final String storage ) {
702                storageType = nval( getRequestParameter( storage ), storageType );
703        }
704        
705        /**
706         * 【TAG】読み取り元バケット名を設定します。
707         * 
708         * @og.tag
709         * ファイルを読み取り元の、バケット名を指定します。
710         * クラウドストレージ利用時のみ有効です。
711         * 未設定の場合は、システムリソースの「CLOUD_BUKET」が参照されます。
712         * 
713         * @og.rev 5.10.9.0 (2019/03/01) 新規追加
714         * 
715         * @param bucket バケット名
716         */
717        public void setBucketName( final String bucket ) {
718                bucketName = nval( getRequestParameter( bucket ), bucketName );
719        }
720        
721        /**
722         * このオブジェクトの文字列表現を返します。
723         * 基本的にデバッグ目的に使用します。
724         *
725         * @og.rev 5.10.9.0 (2019/03/01) storageType, bucketNameを出力対象に追加。
726         * 
727         * @return このクラスの文字列表現
728         */
729        @Override
730        public String toString() {
731                return org.opengion.fukurou.util.ToString.title( this.getClass().getName() )
732                                .println( "VERSION"             ,VERSION        )
733                                .println( "multi"               ,multi  )
734                                .println( "level"               ,level  )
735                                .println( "from"                ,from   )
736                                .println( "storageType" ,storageType    )
737                                .println( "bucketName"  ,bucketName             )
738                                .fixForm().toString()
739                        + HybsSystem.CR
740                        + super.toString() ;
741        }
742}