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.IOException;
022import java.io.ObjectInputStream;
023import java.io.ObjectOutputStream;
024import java.io.Serializable;
025import java.util.Comparator ;
026import java.util.Locale ;
027import java.util.Set ;
028import java.util.TreeSet ;
029
030import org.opengion.fukurou.util.ErrorMessage;
031import org.opengion.fukurou.util.FileUtil;
032import org.opengion.fukurou.util.StringUtil ;
033import org.opengion.hayabusa.common.HybsSystem;
034import org.opengion.hayabusa.common.HybsSystemException;
035import org.opengion.hayabusa.db.DBTableModel;
036import org.opengion.hayabusa.io.HybsFileOperationFactory;
037
038/**
039 * ファイル検索リストを元に、action に基づいた処理を行うタグです。
040 * command="ENTRY" 時のみ処理を行います。
041 *
042 * fileQuery などで検索したファイル一覧のDBTableModel を元に、ファイルの
043 * コピー(COPY)、移動(MOVE,MODIFY)、削除(DELETE)などの処理を行います。
044 * 処理を行うオリジナルファイルは、PARENT,NAME というカラムでなければなりません。
045 * このカラム名は、fileQuery の検索時には、必ず作成されるカラムです。
046 * また、各アクションに対応するターゲットファイルは、TO_PARENT,TO_NAME という
047 * カラムで指定するか、targetDir 属性を利用してフォルダを指定します。
048 * TO_PARENT(先フォルダ)と、TO_NAME(先ファイル名)は、処理に応じて、必要なカラムが
049 * あれば、自動的に処理します。
050 * つまり、TO_PARENT のみの場合は、ファイル名はオリジナルのまま、フォルダのみ変更します。
051 * 逆に、TO_NAME の場合は、フォルダはそのままで、ファイル名のみ指定します。
052 * 両方同時に指定することも可能です。
053 * targetDir 属性で指定する場合は、TO_PARENT のみに同じ値を設定した場合と同じになります。
054 * この属性を指定すると、TO_PARENT は無視されます。(TO_NAME は有効です。)
055 * COPY、MOVE(,MODIFY) の場合は、指定のフォルダに一括処理可能です。
056 * COPY、MOVE(,MODIFY) などの処理で、ターゲットフォルダが存在しないときに、作成するか、エラーにするかは
057 * createDir属性 で指定できます。初期値は、(true:作成する) です。
058 * これは、COPY先やMOVE(,MODIFY)先が存在している前提のシステムで、不要な箇所に間違ってフォルダを
059 * 自動作成されると困る場合に、(false:作成しない) とすれば、間違いに気づく確率が上がります。
060 *
061 * ※ このタグは、Transaction タグの対象ではありません。
062 *
063 * @og.formSample
064 * ●body:なし
065 * ●形式:
066 *      ・<og:fileUpdate
067 *          action      = "COPY|MOVE|MODIFY|DELETE" アクション属性(必須)
068 *          command     = "[ENTRY]"                 ENTRY 時のみ実行します(初期値:ENTRY)
069 *          targetDir   = "[指定フォルダ]"          ターゲットとなるフォルダ
070 *          createDir   = "[true/false]"            ターゲットとなるフォルダがなければ作成する(true)かどうか(初期値:true)
071 *          tableId     = [HybsSystem.TBL_MDL_KEY]  DBTableModel を取り出すキー
072 *          outMessage  = "[true/false]"            検索結果のメッセージを表示する(true)かどうかを指定(初期値:true)
073 *          displayMsg  = "MSG0040";                処理結果を表示します(初期値:「 件登録しました。」)
074 *          selectedAll = "[false/true]"            データを全件選択済みとして処理する(true)かどうか指定(初期値:false)
075 *          keepTimeStamp = "[false/true]"          COPY,親違いMOVE(,MODIFY)の時にオリジナルのタイムスタンプを使用するかどうか(初期値:false)
076 *      />
077 *
078 *    [action属性(必須)]
079 *      COPY   オリジナルファイルを、ターゲット(TO_PARENT,TO_NAMEで指定)にコピーします。
080 *      MOVE   オリジナルファイルを、ターゲットに移動(COPY+DELETE)/名称変更(RENAME)します。
081 *      MODIFY (MOVE と同じ。エンジンの command を利用するための簡易action)
082 *      DELETE オリジナルファイルを削除します(ターゲット(TO_PARENT,TO_NAME)は、関係しません)。
083 *
084 * ●Tag定義:
085 *   <og:fileUpdate
086 *       action           ○【TAG】アクション[COPY|MOVE|MODIFY|DELETE]をセットします(必須)。
087 *       command            【TAG】コマンド[ENTRY]をセットします
088 *       targetDir          【TAG】ターゲットとなるフォルダを指定します
089 *       createDir          【TAG】ターゲットとなるフォルダがなければ、作成するかどうかを指定します(初期値:true)
090 *       tableId            【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します
091 *       outMessage         【TAG】検索結果のメッセージを表示する/しない[true/false]を指定します(初期値:true)
092 *       displayMsg         【TAG】処理結果を画面上に表示するメッセージリソースIDを指定します(初期値:MSG0040[ 件登録しました])
093 *       selectedAll        【TAG】データを全件選択済みとして処理するかどうか[true/false]を指定します(初期値:false)
094 *       keepTimeStamp      【TAG】オリジナルのタイムスタンプを利用するかどうかを指定します(初期値:false)
095 *       caseKey            【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null)
096 *       caseVal            【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null)
097 *       scope              【TAG】キャッシュする場合のスコープ[request/page/session/applicaton]を指定します(初期値:session)
098 *       fromStorageType    【TAG】ターゲットの読み込み元のストレージタイプを指定します(初期値:CLOUD_TARGET)
099 *       fromBucketName      【TAG】ターゲットの読み込み元のバケット名を指定します(初期値:CLOUD_BUCKET)
100 *       toStorageType      【TAG】ターゲットの保存先のストレージタイプを指定します(初期値:CLOUD_TARGET)
101 *       toBucketName        【TAG】ターゲットの保存先のバケット名を指定します(初期値:CLOUD_BUCKET)
102 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
103 *   />
104 *
105 * ●使用例
106 *       ・<og:fileUpdate command="{@command}" action="COPY" />
107 *             TO_PARENT または、 TO_NAME(両方指定も可)による行単位 COPY 処理
108 *             fileQuery の useUpdateClm="true" を設定し、検索結果に、TO_PARENT、 TO_NAMEカラムを追加します。
109 *             TO_PARENT または、 TO_NAME は、columnSet などで値をセットしておきます。
110 *
111 *       ・<og:fileUpdate command="{@command}" action="MODIFY" targetDir="AAA_DIR"  />
112 *             fileQuery の検索結果を、AAA_DIR フォルダに移動します。
113 *             ファイル名は、そのままオリジナルの値が使用されます。
114 *
115 * @og.rev 5.3.4.0 (2011/04/01) 新規追加
116 * @og.rev 5.10.9.0 (2019/03/01) oota クラウドストレージ対応を追加。(Fileクラスを拡張)
117 * 
118 * @og.group ファイル出力
119 *
120 * @version  4.0
121 * @author       Kazuhiko Hasegawa
122 * @since    JDK5.0,
123 */
124public class FileUpdateTag extends CommonTagSupport {
125        //* このプログラムのVERSION文字列を設定します。   {@value} */
126        private static final String VERSION = "5.6.5.2 (2013/06/21)" ;
127
128        private static final long serialVersionUID = 565220130621L ;
129
130        /** command 引数に渡す事の出来る コマンド  登録{@value} */
131        public static final String CMD_ENTRY  = "ENTRY" ;
132        /** command 引数に渡す事の出来る コマンド リスト  */
133        private static  final String COMMAND_LIST = CMD_ENTRY;
134
135        /** エラーメッセージID {@value} */
136        private static final String errMsgId     = HybsSystem.ERR_MSG_KEY;
137
138        /** action 引数に渡す事の出来る アクションコマンド  COPY {@value} */
139        public static final String ACT_COPY             = "COPY" ;
140        /** action 引数に渡す事の出来る アクションコマンド  MOVE {@value} */
141        public static final String ACT_MOVE             = "MOVE" ;
142        /** action 引数に渡す事の出来る アクションコマンド  MODIFY {@value} */
143        public static final String ACT_MODIFY           = "MODIFY" ;
144        /** action 引数に渡す事の出来る アクションコマンド  DELETE {@value} */
145        public static final String ACT_DELETE   = "DELETE" ;
146
147        private static final String[] ACTION_LIST = new String[] { ACT_COPY , ACT_MOVE , ACT_MODIFY , ACT_DELETE };
148
149        private String  action          = null;
150        private String  targetDir       = null;         // ターゲットとなるフォルダ
151        private boolean createDir       = true;         // ターゲットとなるフォルダがなければ、作成するかどうか(true:作成する)
152
153        private String  tableId         = HybsSystem.TBL_MDL_KEY;
154        private String  command         = CMD_ENTRY;
155        private boolean outMessage      = true;
156        private String  displayMsg      = "MSG0040";    //  件登録しました。
157        private boolean selectedAll = false;
158        private boolean keepTimeStamp = false;          // オリジナルのタイムスタンプを利用する場合、true
159
160        private transient DBTableModel  table           = null;
161        private transient ErrorMessage  errMessage      = null;
162        private int             executeCount    = -1;                   // 処理件数
163        private int             errCode                 = ErrorMessage.OK;
164        private long    dyStart                 = 0;
165        
166        private String fromStorageType = null;          // 5.10.9.0 (2019/03/01) ADD 
167        private String fromBucketName = null;           // 5.10.9.0 (2019/03/01) ADD
168        private String toStorageType = null;            // 5.10.9.0 (2019/03/01) ADD
169        private String toBucketName = null;                     // 5.10.9.0 (2019/03/01) ADD
170
171        /**
172         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
173         * 
174         * @og.rev 5.10.2.2 (2018/08/24) 一部のエラーをjspPrintから標準のErrorMessageに変更
175         *
176         * @return      後続処理の指示
177         */
178        @Override
179        public int doEndTag() {
180                debugPrint();
181                // 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
182                if( !useTag() ) { return(EVAL_PAGE); }
183
184                dyStart = System.currentTimeMillis();
185
186                table = (DBTableModel)getObject( tableId );
187
188                String label  = "";                             // 4.0.0 (2005/11/30) 検索しなかった場合。
189                if( table != null && table.getRowCount() > 0 && check( command, COMMAND_LIST ) ) {
190                        startQueryTransaction( tableId );
191
192                        execute();      // 実際の処理を実行します。
193
194                        StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_SMALL );
195
196                        setRequestAttribute( "DB.COUNT"   , String.valueOf( executeCount ) );
197                        setRequestAttribute( "DB.ERR_CODE", String.valueOf( errCode ) );
198                        
199                        // 5.10.2.2 (2018/08/24) 6.9.9.0 「ERR0041:検索処理中に割り込みの検索要求がありました」エラーを、標準のErrorMessageに追加するようにします。
200                        if( ! commitTableObject( tableId, table ) ) {
201                                if( errMessage == null ) { errMessage = new ErrorMessage( "FileUpdateTag Query Error!" ); }
202                                // ERR0041:検索処理中に割り込みの検索要求がありました。処理されません。
203                                errMessage.addMessage( 0,ErrorMessage.NG,"ERR0041" );   
204                                errCode = ErrorMessage.NG;
205                        }
206
207                        String err = TaglibUtil.makeHTMLErrorTable( errMessage,getResource() );
208                        if( err != null && err.length() > 0 ) {
209                                buf.append( err );
210                                setSessionAttribute( errMsgId,errMessage );
211                        }
212                        label = buf.toString();
213                        
214//                      // 5.10.2.2 (2018/08/24) 6.9.9.0
215//                      if( table != null && ! commitTableObject( tableId, table ) ) {
216//                              jspPrint( "FileUpdateTag Query処理が割り込まれました。DBTableModel は登録しません。" );
217//                              return (SKIP_PAGE);
218//                      }
219                }
220
221                jspPrint( label );
222
223                // 実行件数の表示
224                // 4.0.0 (2005/11/30) 出力順の変更。一番最初に出力します。
225                if( displayMsg != null && displayMsg.length() > 0 ) {
226                        String status = executeCount + getResource().getLabel( displayMsg ) ;
227                        jspPrint( status + HybsSystem.BR );
228                }
229
230                // 3.5.4.7 (2004/02/06)
231                long dyTime = System.currentTimeMillis()-dyStart;
232                jspPrint( "<div id=\"queryTime\" value=\"" + (dyTime) + "\"></div>" );      // 3.5.6.3 (2004/07/12)
233
234                return( EVAL_PAGE );
235        }
236
237        /**
238         * タグリブオブジェクトをリリースします。
239         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
240         *
241         * @og.rev 5.10.9.0 (2019/03/01) 属性にfromStorageType,fromBucketName,toStorageType,toBucketNameを追加。
242         */
243        @Override
244        protected void release2() {
245                super.release2();
246                tableId         = HybsSystem.TBL_MDL_KEY;
247                command         = CMD_ENTRY;
248                action          = null;
249                targetDir       = null;         // ターゲットとなるフォルダ
250                createDir       = true;         // ターゲットとなるフォルダがなければ、作成するかどうか(true:作成する)
251                outMessage      = true;
252                displayMsg      = "MSG0040";    //  件登録しました。
253                selectedAll = false;
254                keepTimeStamp = false;          // オリジナルのタイムスタンプを利用する場合、true
255                table           = null;
256                errMessage      = null;
257                executeCount= -1;               // 処理件数
258                errCode         = ErrorMessage.OK;
259                dyStart         = 0;            // 処理時間
260                fromStorageType = null;         // 5.10.9.0 (2019/03/01) ADD
261                fromBucketName = null;          // 5.10.9.0 (2019/03/01) ADD
262                toStorageType = null;           // 5.10.9.0 (2019/03/01) ADD
263                toBucketName = null;                    // 5.10.9.0 (2019/03/01) ADD
264        }
265
266        /**
267         * 処理を実行します。
268         *
269         * @og.rev 5.10.9.0 (2019/03/01) クラウドストレージ対応を追加。
270         */
271        private void execute() {
272                int[] rowNo = getParameterRows();
273                if( rowNo.length > 0 ) {
274
275                        // 5.10.9.0 (2019/03/01) MODIFY
276//                      FromToFiles fromToFiles = new FromToFiles( table , targetDir , createDir );
277                        FromToFiles fromToFiles = new FromToFiles( table, targetDir, createDir, toStorageType, toBucketName);
278                        
279                        if( ACT_COPY.equalsIgnoreCase( action ) ) {
280                                actionCOPY( rowNo,fromToFiles );
281                        }
282                        // ACT_MODIFY は、エンジンの command で使うため、便利
283                        else if( ACT_MOVE.equalsIgnoreCase( action ) || ACT_MODIFY.equalsIgnoreCase( action ) ) {
284                                actionMOVE( rowNo,fromToFiles );
285                        }
286                        else if( ACT_DELETE.equalsIgnoreCase( action ) ) {
287                                actionDELETE( rowNo,fromToFiles );
288                        }
289                }
290        }
291
292        /**
293         * COPY アクションを実行します。
294         *
295         * @og.rev 5.6.5.2 (2013/06/21) From側がファイルの場合のみ処理します。
296         * @og.rev 5.10.9.0 (2019/03/01) クラウドストレージ対応を追加。
297         *
298         * @param       rowNo           処理を実施する行番号
299         * @param       fromToFiles     FromFile,ToFile をまとめた補助クラス
300         * @throws      HybsSystemException     処理中に何らかのエラーが発生した場合
301         */
302        private void actionCOPY( final int[] rowNo , final FromToFiles fromToFiles ) {
303                File fromFile = null ;
304                File toFile   = null ;
305
306                executeCount = 0 ;      // 開始前に初期化しておく。
307                int rowCount = rowNo.length ;
308                for( int i=0; i<rowCount; i++ ) {
309                        // 5.10.9.0 (2019/03/01) MODIFY
310//                      File[] files = fromToFiles.makeFromToFile( rowNo[i] );  // FromFile,ToFile
311                        File[] files = fromToFiles.makeFromToFile( rowNo[i], fromStorageType, fromBucketName, toStorageType, toBucketName);
312                        fromFile = files[0];
313                        toFile   = files[1];
314
315                        // 5.6.5.2 (2013/06/21) From側がファイルの場合のみ処理します。
316//                      if( !FileUtil.copy( fromFile,toFile,keepTimeStamp ) ) {
317                        if( fromFile.isFile() && !FileUtil.copy( fromFile,toFile,keepTimeStamp )) {
318                                String errMsg = "アクション=[" + action + "]中にエラーが発生しました。" + HybsSystem.CR
319                                                                        + "From=[" + fromFile + "],To=[" + toFile + "]" + HybsSystem.CR;
320                                throw new HybsSystemException( errMsg );
321                        }
322                        executeCount++ ;
323                }
324        }
325
326        /**
327         * MOVE アクションを実行します。
328         *
329         * @og.rev 5.5.2.4 (2012/05/16) メソッドの戻り値の設定
330         * @og.rev 5.6.5.2 (2013/06/21) From側がファイルの場合のみ処理します。
331         * @og.rev 5.10.9.0 (2019/03/01) クラウドストレージの対応を追加。
332         *
333         * @param       rowNo           処理を実施する行番号
334         * @param       fromToFiles     FromFile,ToFile をまとめた補助クラス
335         * @throws      HybsSystemException     処理中に何らかのエラーが発生した場合
336         */
337        private void actionMOVE( final int[] rowNo , final FromToFiles fromToFiles ) {
338                File fromFile = null ;
339                File toFile   = null ;
340
341                executeCount = 0 ;      // 開始前に初期化しておく。
342                int rowCount = rowNo.length ;
343                for( int i=0; i<rowCount; i++ ) {
344                        // 5.10.9.0 (2019/03/01) MODIFY
345                        // File[] files = fromToFiles.makeFromToFile( rowNo[i] );       // FromFile,ToFile
346                        File[] files = fromToFiles.makeFromToFile( rowNo[i], fromStorageType, fromBucketName, toStorageType, toBucketName);
347                        fromFile = files[0];
348                        toFile   = files[1];
349
350                        if( fromToFiles.lastParentEquals() ) {  // FromDirとToDirが同じなので、RENAMEできる。
351                                if( !fromFile.renameTo( toFile ) ) {
352                                        String errMsg = "アクション=[" + action + "]中にエラーが発生しました。" + HybsSystem.CR
353                                                                                + "同一親フォルダのため、RENAME処理を行っています。" + HybsSystem.CR
354                                                                                + "From=[" + fromFile + "],To=[" + toFile + "]" + HybsSystem.CR;
355                                        throw new HybsSystemException( errMsg );
356                                }
357                        }
358                        // 5.6.5.2 (2013/06/21) From側がファイルの場合のみ処理します。
359//                      else {                  // FromDirとToDirが異なるので、COPY + DELETE する。
360                        else if( fromFile.isFile() ) {                  // FromDirとToDirが異なるので、COPY + DELETE する。
361                                if( !FileUtil.copy( fromFile,toFile,keepTimeStamp ) ) {
362                                        String errMsg = "アクション=[" + action + "]中にエラーが発生しました。" + HybsSystem.CR
363                                                                                + "移動前のCOPY処理を行っていました。" + HybsSystem.CR
364                                                                                + "From=[" + fromFile + "],To=[" + toFile + "]" + HybsSystem.CR;
365                                        throw new HybsSystemException( errMsg );
366                                }
367
368                                if( !fromFile.delete() ) {
369//                                      toFile.delete();        // 移動の際の COPY は正常なので、まずは、そのファイルを削除しておく。
370                                        String errMsg = "アクション=[" + action + "]中にエラーが発生しました。" + HybsSystem.CR
371                                                                                + "移動後のオリジナルファイルの削除処理を行っていました。" + HybsSystem.CR
372                                                                                + "From=[" + fromFile + "],To=[" + toFile + "]" + HybsSystem.CR;
373                                        // 5.5.2.4 (2012/05/16) メソッドの戻り値の設定
374                                        if(! toFile.delete() ) {
375                                                errMsg = errMsg + "toFile も削除に失敗しました。" + HybsSystem.CR;
376                                        }
377
378                                        throw new HybsSystemException( errMsg );
379                                }
380                        }
381                        executeCount++ ;
382                }
383        }
384
385        /**
386         * DELETE アクションを実行します。
387         *
388         * この処理では、リストにフォルダが含まれている場合も削除します。
389         * 通常、フォルダの削除は、その要素(内部)にファイル等が存在しない場合のみ
390         * 行いますが、検索リストから削除する順番によっては、フォルダもファイルも
391         * 削除対象になる場合があります。そこで、まず。ファイルだけ削除し、フォルダは、
392         * あとで削除するように処理を行います。
393         *
394         * @og.rev 5.6.5.2 (2013/06/21) フォルダも削除対象にします。
395         * @og.rev 5.10.9.0 (2019/03/01) クラウドストレージの対応を追加。
396         *
397         * @param       rowNo           処理を実施する行番号
398         * @param       fromToFiles     FromFile,ToFile をまとめた補助クラス
399         * @throws      HybsSystemException     処理中に何らかのエラーが発生した場合
400         */
401        private void actionDELETE( final int[] rowNo , final FromToFiles fromToFiles ) {
402                File fromFile = null;
403
404                // 5.6.5.2 (2013/06/21) フォルダを削除する為の、退避
405                Set<File> dirSet = new TreeSet<File>( new FileNameLengthComparator() );             // ファイルの文字数順に並べたSet
406
407                executeCount = 0 ;      // 開始前に初期化しておく。
408                int rowCount = rowNo.length ;
409                for( int i=0; i<rowCount; i++ ) {
410                        // 5.10.9.0 (2019/03/01) MODIFY
411//                      fromFile = fromToFiles.makeFromOnly( rowNo[i] );        // FromFile
412                        fromFile = fromToFiles.makeFromOnly(rowNo[i], fromStorageType, fromBucketName);
413                        
414                        // 5.6.5.2 (2013/06/21) まず、ファイルを削除します。
415//                      if( !fromFile.delete() ) 
416                        if( fromFile.isFile() ) {
417                                if( !fromFile.delete() ) {
418                                        String errMsg = "アクション=[" + action + "]中にエラーが発生しました。" + HybsSystem.CR
419                                                                                + "From=[" + fromFile + "]" + HybsSystem.CR;
420                                        throw new HybsSystemException( errMsg );
421                                }
422                        }
423                        else {
424                                // 5.6.5.2 (2013/06/21) フォルダの場合は、アドレスの桁数をキーにソートしておきます。
425                                int len = fromFile.getAbsolutePath().length();
426                                dirSet.add( fromFile );
427                        }
428                        executeCount++ ;
429                }
430
431                // 5.6.5.2 (2013/06/21) フォルダの削除は、アドレスの桁数の大きい順(階層の深い順)に削除します。
432                for( File file : dirSet ) {
433                        if( !file.delete() ) {
434                                String errMsg = "アクション=[" + action + "]中にエラーが発生しました。" + HybsSystem.CR
435                                                                        + "From(Dir)=[" + file + "]" + HybsSystem.CR;
436                                throw new HybsSystemException( errMsg );
437                        }
438                }
439        }
440
441        /**
442         * ファイルの名称の長さ順(長い順)に比較する、Comparator インターフェースの実装クラス
443         *
444         * ここでの大小比較は、ファイル名の文字数が、大きい方が、小さいとみなされます。
445         * つまり階層が深いので、先に処理する必要があるという事を意味します。
446         * 処理としては、f1 != null &amp;&amp; f2 != null で、len1 = f1.getAbsolutePath().length() と len2 = f2.getAbsolutePath().length() を比較し
447         * len1 &gt; len2 ⇒ 負 , len1 &lt; len2 ⇒ 正 , len1 == len2 ⇒ 0 を返します。
448         * 具体的には、return ( len2 - len1 ); です。
449         * 
450         * 注: このコンパレータは equals と一貫性のない順序付けを課します。
451         * 
452         * @og.rev 5.6.5.2 (2013/06/21) 新規追加
453         * 
454         */
455        private static final class FileNameLengthComparator implements Comparator<File> , Serializable {
456                private static final long serialVersionUID = 5652 ;             // 5.6.5.2 (2013/06/21)
457                /**
458                 * 順序付けのために 2 つの引数を比較します。
459                 *
460                 * ここでの大小比較は、ファイル名の文字数が、大きい方が、小さいとみなされます。
461                 * 具体的には、return ( len2 - len1 ); です。
462                 * 
463                 * @param       比較対象の最初のオブジェクト
464                 * @param       比較対象の 2 番目のオブジェクト
465                 * @return      最初の引数が 2 番目の引数より小さい場合は負の整数、両方が等しい場合は 0、最初の引数が 2 番目の引数より大きい場合は正の整数
466                 */
467                public int compare( final File f1 , final File f2 ) {
468                        if( f1 == null || f2 == null ) {
469                                String errMsg = "引数のFileにnullが含まれています。file1=[" + f1 + "] , file2=[" + f2 + "]" ;
470                                throw new IllegalArgumentException( errMsg );
471                        }
472
473                        int len1 = f1.getAbsolutePath().length();
474                        int len2 = f2.getAbsolutePath().length();
475
476                        return ( len2 - len1 );
477                }
478        }
479
480        /**
481         * 表示データの HybsSystem.ROW_SEL_KEY を元に、選ばれた 行を処理の対象とします。
482         *
483         * @return      選択行の配列
484         */
485        @Override
486        protected int[] getParameterRows() {
487                final int[] rowNo ;
488                if( selectedAll ) {
489                        int rowCnt = table.getRowCount();
490                        rowNo = new int[ rowCnt ];
491                        for( int i=0; i<rowCnt; i++ ) {
492                                rowNo[i] = i;
493                        }
494                } else {
495                        rowNo = super.getParameterRows();
496                }
497                return rowNo ;
498        }
499
500        /**
501         * 【TAG】アクション[COPY|MOVE|MODIFY|DELETE]をセットします(必須)。
502         *
503         * @og.tag
504         * アクションは、ファイルをコピー(COPY)したり、移動(MOVE,MODIFY)したり、削除(DELETE)する
505         * などの操作を指定する必須属性です。
506         *
507         * <table border="1" frame="box" rules="all" >
508         *   <caption>action属性(必須)のキーワード</caption>
509         *   <tr><th>action</th><th>名称</th><th>機能</th></tr>
510         *   <tr><td>COPY  </td><td>コピー</td><td>オリジナルファイルを、ターゲット(TO_PARENT,TO_NAMEで指定)にコピーします。</td></tr>
511         *   <tr><td>MOVE  </td><td>移動  </td><td>オリジナルファイルを、ターゲットに移動(COPY+DELETE)/名称変更(RENAME)します。</td></tr>
512         *   <tr><td>MODIFY</td><td>移動  </td><td>(MOVE と同じ。エンジンの command を利用するための簡易action)</td></tr>
513         *   <tr><td>DELETE</td><td>削除  </td><td>オリジナルファイルを、削除します。(フォルダ、ファイルに関わらず)</td></tr>
514         * </table>
515         *
516         * @param       act アクション(public static final 宣言されている文字列)
517         * @see         <a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.FileUpdateTag.ACT_COPY">アクション定数</a>
518         */
519        public void setAction( final String act ) {
520                action = nval( getRequestParameter( act ),action );
521
522                if( action != null && !check( action, ACTION_LIST ) ) {
523                        String errMsg = "指定のアクションは実行できません。アクションエラー" + HybsSystem.CR
524                                                        + "action=[" + action + "] "                                            + HybsSystem.CR
525                                                        + StringUtil.array2csv( ACTION_LIST ) ;
526                        throw new HybsSystemException( errMsg );
527                }
528        }
529
530        /**
531         * 【TAG】ターゲットとなるフォルダを指定します。
532         *
533         * @og.tag
534         * targetDir 属性を利用する場合は、引数のファイル、またはフォルダが指定されたことに
535         * なります。COPY、MOVE(,MODIFY) の場合は、targetDir 属性にフォルダを指定することで一括処理可能です。
536         * 指定先のフォルダが存在しない場合は、createDir属性の値により処理が異なります。
537         * createDir="true"(初期値)で、ターゲットフォルダが存在しない場合は、自動作成します。
538         *
539         * @param  dir ターゲットとなるフォルダ
540         * @see         #setCreateDir( String )
541         */
542        public void setTargetDir( final String dir ) {
543                targetDir = nval( getRequestParameter( dir ),targetDir );
544        }
545
546        /**
547         * 【TAG】ターゲットとなるフォルダがなければ、作成するかどうかを指定します(初期値:true)。
548         *
549         * @og.tag
550         * COPY,MOVE(,MODIFY) などの処理で、ターゲットフォルダが存在しないときに、作成するか、エラーにするかを
551         * createDir属性 で指定できます。
552         * これは、COPY先やMOVE(,MODIFY)先が存在している前提のシステムで、不要な箇所に間違ってフォルダを
553         * 自動作成されると困る場合に、false:作成しない とすれば、間違いに気づく確率が上がります。
554         * 初期値は true:作成する です。
555         *
556         * @param  flag ターゲットとなるフォルダを自動作成する(true)か、しない(false) 初期値は、true:作成する
557         */
558        public void setCreateDir( final String flag ) {
559                createDir = nval( getRequestParameter( flag ),createDir );
560        }
561
562        /**
563         * 【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します
564         *              (初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])。
565         *
566         * @og.tag
567         * 検索結果より、DBTableModelオブジェクトを作成します。これを、下流のviewタグ等に
568         * 渡す場合に、通常は、session を利用します。その場合の登録キーです。
569         * query タグを同時に実行して、結果を求める場合、同一メモリに配置される為、
570         * この tableId 属性を利用して、メモリ空間を分けます。
571         *              (初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])。
572         *
573         * @param       id sessionに登録する時の ID
574         */
575        public void setTableId( final String id ) {
576                tableId = nval( getRequestParameter( id ),tableId );
577        }
578
579        /**
580         * 【TAG】コマンド(ENTRY)をセットします。
581         *
582         * @og.tag
583         * このタグは、command="ENTRY" でのみ実行されます。
584         * コマンドは,HTMLから(get/post)指定されますので,CMD_xxx で設定される
585         * フィールド定数値のいづれかを、指定できます。
586         * 初期値は、ENTRY なので、何も指定しなければ、実行されます。
587         *
588         * @param       cmd コマンド(public static final 宣言されている文字列)
589         * @see         <a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.FileUpdateTag.CMD_ENTRY">コマンド定数</a>
590         */
591        public void setCommand( final String cmd ) {
592                String cmd2 = getRequestParameter( cmd );
593                if( cmd2 != null && cmd2.length() >= 0 ) { command = cmd2.toUpperCase(Locale.JAPAN); }
594        }
595
596        /**
597         * 【TAG】検索結果のメッセージを表示する/しない[true/false]を指定します(初期値:true)。
598         *
599         * @og.tag
600         * 初期値は、表示する:true です。
601         *
602         * @param       flag  [true:表示する/それ以外:含めない]
603         */
604        public void setOutMessage( final String flag ) {
605                outMessage = nval( getRequestParameter( flag ),outMessage );
606        }
607
608        /**
609         * 【TAG】処理結果を画面上に表示するメッセージリソースIDを指定します(初期値:MSG0040[ 件登録しました])。
610         *
611         * @og.tag
612         * ここでは、検索結果の件数や登録された件数をまず出力し、
613         * その次に、ここで指定したメッセージをリソースから取得して表示します。
614         * 表示させたくない場合は, displayMsg = "" をセットしてください。
615         * displayMsg の初期値は、MSG0040[ 件登録しました]です。
616         *
617         * @param       id ディスプレイに表示させるメッセージ ID
618         */
619        public void setDisplayMsg( final String id ) {
620                String ids = getRequestParameter( id );
621                if( ids != null ) { displayMsg = ids; }
622        }
623
624        /**
625         * 【TAG】データを全件選択済みとして処理するかどうか[true/false]を指定します(初期値:false)。
626         *
627         * @og.tag
628         * 全てのデータを選択済みデータとして扱って処理します。
629         * 全件処理する場合に、(true/false)を指定します。
630         * 初期値は false です。
631         *
632         * @param  all データを全件選択済み [true:全件選択済み/false:通常]
633         */
634        public void setSelectedAll( final String all ) {
635                selectedAll = nval( getRequestParameter( all ),selectedAll );
636        }
637
638        /**
639         * 【TAG】オリジナルのタイムスタンプを利用するかどうかを指定します(初期値:false)。
640         *
641         * @og.tag
642         * COPYや親違いMOVE(,MODIFY)の時に、オリジナルのタイムスタンプをそのままコピー先のファイルにも
643         * 適用するかどうかを指定します。
644         * タイムスタンプを初期化されたくない場合に、true に設定します。
645         * 初期値は 利用しない:false です。
646         *
647         * @param  flag タイムスタンプを利用するかどう(初期値:利用しない)。
648         */
649        public void setKeepTimeStamp( final String flag ) {
650                keepTimeStamp = nval( getRequestParameter( flag ),keepTimeStamp );
651        }
652
653        /**
654         * 【TAG】読み取り元ストレージタイプを設定します。
655         *  
656         * @og.tag
657         * ファイルを読み取り元の、ストレージタイプを設定します。
658         * 未設定の場合は、システムリソースの「CLOUD_TARGET」が参照されます。
659         * 自身のサーバを指定する場合は、「default」を設定してください。
660         * 
661         * @og.rev 5.10.9.0 (2019/03/01) 新規追加
662         * 
663         * @param fromStorage 読み取り元ストレージタイプ
664         */
665        public void setFromStorageType( final String fromStorage ) {
666                fromStorageType = nval( getRequestParameter( fromStorage ), fromStorageType );
667        }
668        
669        /**
670         * 【TAG】読み取り元バケット名を設定します。
671         * 
672         * @og.tag
673         * ファイルを読み取り元の、バケット名を指定します。
674         * クラウドストレージ利用時のみ有効です。
675         * 未設定の場合は、システムリソースの「CLOUD_BUKET」が参照されます。
676         * 
677         * @og.rev 5.10.9.0 (2019/03/01) 新規追加
678         * 
679         * @param fromBucket 読み取り元バケット名
680         */
681        public void setFromBucketName( final String fromBucket ) {
682                fromBucketName = nval( getRequestParameter( fromBucket ), fromBucketName );
683        }
684        
685        /**
686         * 【TAG】保存先ストレージタイプを設定します。
687         *  
688         * @og.tag
689         * ファイルを保存先の、ストレージタイプを設定します。
690         * 未設定の場合は、システムリソースの「CLOUD_TARGET」が参照されます。
691         * 自身のサーバを指定する場合は、「default」を設定してください。
692         * 
693         * @og.rev 5.10.9.0 (2019/03/01) 新規追加
694         * 
695         * @param toStorage 保存先ストレージタイプ
696         */
697        public void setToStorageType( final String toStorage ) {
698                toStorageType = nval( getRequestParameter( toStorage ), toStorageType );
699        }
700        
701        /**
702         * 【TAG】保存先バケット名を設定します。
703         * 
704         * @og.tag
705         * ファイルを読み取り元の、バケット名を指定します。
706         * クラウドストレージ利用時のみ有効です。
707         * 未設定の場合は、システムリソースの「CLOUD_BUKET」が参照されます。
708         * 
709         * @og.rev 5.10.9.0 (2019/03/01) 新規追加
710         * 
711         * @param toBucket 保存先バケット名
712         */
713        public void setToBucketName( final String toBucket ) {
714                toBucketName = nval( getRequestParameter( toBucket ), toBucketName );
715        }
716        
717        /**
718         * DBTableModel から、FromFile,ToFile を作成するための処理をまとめた補助クラスです。
719         *
720         * ここでは、オリジナルファイルやターゲットファイルを作成するための処理のみを集めています。
721         * メソッドにすると、ローカル変数を多く管理するか、多数の引数渡しを繰り返すことになるため、
722         * このローカルクラスに処理と、値を格納します。
723         *
724         */
725        private static final class FromToFiles {
726//              private static final String[] CLMS_LIST   = new String[] { "PARENT","NAME","TO_PARENT","TO_NAME" };
727
728                private final DBTableModel      table ;
729
730                private final int PARENT        ;
731                private final int NAME          ;
732                private final int TO_PARENT     ;
733                private final int TO_NAME       ;
734
735                private final File    toDir     ;
736                private final boolean createDir;        // ターゲットとなるフォルダがなければ、作成するかどうか(true:作成する)
737
738                private boolean equalParent = false;    // 最後に実行された処理で、親フォルダが同一の場合は、true
739
740                /**
741                 *  引数指定のコンストラクター
742                 *
743                 * 必要なパラメータを渡して、オブジェクトを構築します。
744                 *
745                 * @param       table     DBTableModel  一覧が格納されているDBTableModel
746                 * @param       targetDir       ターゲットとなるフォルダ
747                 * @param       createDir       ターゲットとなるフォルダがなければ、作成するかどうか(true:作成する)
748                 * @param  targetStorageType ターゲットのストレージタイプ
749                 * @param  targetBucketName   ターゲットのバケット名
750                 */
751                
752                // public FromToFiles( final DBTableModel table , final String targetDir , final boolean createDir ) {
753                public FromToFiles( final DBTableModel table , final String targetDir , final boolean createDir,
754                                final String targetStorageType, final String targetBucketName) {
755                        this.table              = table;
756                        this.createDir  = createDir ;
757                        
758                        // 5.10.9.0 (2019/03/01) MODIFY
759                        // toDir = mkDirs( targetDir,createDir );       // targetDir が指定されていない場合は、null
760                        toDir = mkDirs( targetDir,createDir,targetStorageType,targetBucketName );
761
762                        // "PARENT","NAME","TO_PARENT","TO_NAME" のカラム名のDBTableModelのカラム番号。存在しない場合は、-1
763                        PARENT          = table.getColumnNo( "PARENT"   , false );
764                        NAME            = table.getColumnNo( "NAME"             , false );
765                        TO_PARENT       = table.getColumnNo( "TO_PARENT", false );
766                        TO_NAME         = table.getColumnNo( "TO_NAME"  , false );
767                }
768
769                /**
770                 * 行番号より、対応するオリジナルファイル(FromFile)を返します。
771                 *
772                 * ここでは、TO_PARENT や TO_NAME は、判定する必要がないため、makeFromToFile( int ) の
773                 * 一部のみで処理が終了できます。
774                 * 1.FromDir は、PARENT 列の値から作成する。
775                 * 2.FromFileは、FromDir + NAME列の値から作成する。
776                 *
777                 * 配列返しの関係で、メソッド(および内部処理)を分けています。
778                 *
779                 * @og.rev 5.10.9.0 (2019/03/01) クラウドストレージ対応を追加。
780                 *
781                 * @param       rowNo   カラムNo
782                 * @param  fromStorageType オリジナルファイルのストレージタイプ
783                 * @param  fromBucketName オリジナルファイルのバケット名
784                 * @return      File オリジナルファイル(FromFile)
785                 * @see         #makeFromToFile( int )
786                 */
787                // 5.10.9.0 (2019/03/01) MODIFY
788                // public File makeFromOnly( final int rowNo ) {
789                public File makeFromOnly( final int rowNo, final String fromStorageType, final String fromBucketName ) {
790                        String[] value = table.getValues( rowNo );
791                        
792                        // 5.10.9.0 (2019/03/01) MODIFY
793//                      File fromDir = mkDirs( value[PARENT],createDir);
794                        File fromDir = mkDirs( value[PARENT],createDir,fromStorageType,fromBucketName );
795
796                        // 5.10.9.0 (2019/03/01) MODIFY
797//                      return new File( fromDir, value[NAME] ) ;
798                        return HybsFileOperationFactory.create( fromStorageType, fromBucketName, fromDir, value[NAME] ); 
799                }
800
801                /**
802                 * 行番号より、対応するオリジナルファイル(FromFile)とターゲットファイル(ToFile)を配列に格納して返します。
803                 *
804                 * ここでは、TO_PARENT や TO_NAME は、存在するかどうか不明なので、以下の手順で作成します。
805                 * 1.FromDir は、PARENT 列の値から作成する。
806                 * 2.FromFileは、FromDir + NAME列の値から作成する。
807                 * 3.toDir は、
808                 *       A.targetDir が有れば、それを使う。
809                 *       B.なければ、TO_PARENT 列の値から作成する。
810                 *       C.TO_PARENT 列がないか、値が未設定の場合は、FromDir をそのまま使う。
811                 * 4.toFile は、
812                 *       A.toDir + TO_NAME 列の値から作成する。
813                 *       B.TO_NAME 列がないか、値が未設定の場合は、toDir + NAME列の値から作成する。
814                 * 返り値は、new File[] { formFile , toFile }; とする。
815                 *
816                 * @og.rev 5.10.9.0 (2019/03/01) クラウドストレージ対応を追加。
817                 * 
818                 * @param       rowNo   カラムNo
819                 * @param  fromStorageType オリジナルファイルのストレージタイプ 
820                 * @param  fromBucketName   オリジナルファイルのバケット名
821                 * @param  toStorageType   ターゲットファイルのストレージタイプ
822                 * @param  toBucketName     ターゲットファイルのバケット名
823                 * 
824                 * @return      File[] ファイル配列(0:オリジナルファイル 1:ターゲットファイル)
825                 */
826                // 5.10.9.0 (2019/03/01) MODIFY
827                // public File[] makeFromToFile( final int rowNo ) {
828                public File[] makeFromToFile( final int rowNo, final String fromStorageType, final String fromBucketName,
829                                final String toStorageType, final String toBucketName) {
830
831                        String[] value = table.getValues( rowNo );
832                        // 5.10.9.0 (2019/03/01) MODIFY
833                        // File fromDir  = mkDirs( value[PARENT],createDir );
834                        File fromDir  = mkDirs( value[PARENT],createDir,fromStorageType,fromBucketName );
835                        // 5.10.9.0 (2019/03/01) MODIFY
836//                      File formFile = new File( fromDir, value[NAME] )
837                        File fromFile = HybsFileOperationFactory.create(fromStorageType, fromBucketName, fromDir, value[NAME]);
838                        File tempToDir = toDir;
839
840                        equalParent = false;    // 最後に実行された処理で、親フォルダが同一かどうかのフラグをリセットする。
841                        if( tempToDir == null ) {
842                                if( TO_PARENT >= 0 && nval(value[TO_PARENT],null) != null ) {
843                                        // 5.10.9.0 (2019/03/01) MODIFY
844//                                      tempToDir = mkDirs( value[TO_PARENT],createDir );
845                                        tempToDir = mkDirs( value[TO_PARENT],createDir,toStorageType,toBucketName );
846                                }
847                                else  {
848                                        tempToDir = fromDir;
849                                        equalParent = true;             // 最後に実行された処理で、親フォルダが同一の場合は、true
850                                }
851                        }
852                        File toFile = null;
853                        if( TO_NAME >= 0 && nval(value[TO_NAME],null) != null  ) {
854                                // 5.10.9.0 (2019/03/01) MODIFY 
855//                              toFile = new File( tempToDir, value[TO_NAME] );
856                                toFile = HybsFileOperationFactory.create(toStorageType, toBucketName, tempToDir, value[TO_NAME] );
857                        }
858                        else {
859                                // 5.10.9.0 (2019/03/01) MODIFY
860//                              toFile = new File( tempToDir, value[NAME] );
861                                toFile = HybsFileOperationFactory.create(toStorageType, toBucketName, tempToDir, value[NAME]);
862                                
863                        }
864
865                        return new File[] { fromFile , toFile };
866                }
867
868                /**
869                 * 最後に実行された処理で、親フォルダが同一かどうかを返します(同一の場合は、true)。
870                 *
871                 * makeFromToFile( int ) が処理されたときの、FromDir と toDir が同一であれば、true を、
872                 * 異なる場合は、false を返します。
873                 * ここでの結果は、厳密な同一判定ではなく、処理的に、同一かどうかを判定しています。
874                 * つまり、toDir に FromDir をセットする(3.Cのケース)場合に、true を内部変数にセットします。
875                 * この判定値は、ファイルの移動処理で、異なる親フォルダの場合は、COPY & DELETE しなければ
876                 * なりませんが、同一親フォルダの場合は、RENAME で済む という処理負荷の軽減が目的です。
877                 * よって、結果的に、PARENT と TO_PARENT が同じとか、PARENT と targetDir が同じでも
878                 * ここでのフラグは、false が返されます。
879                 *
880                 * @return      最後に実行された処理で、親フォルダが同一の場合は、true
881                 * @see         #makeFromToFile( int )
882                 */
883                public boolean lastParentEquals() {
884                        return equalParent ;
885                }
886
887                /**
888                 *  カラム名配列(String[])より、対応するカラムNo配列(int[])を作成します。
889                 *
890                 * ここでは、TO_PARENT や TO_NAME は、存在するかどうか不明なので、
891                 * EXCEPTION にせず、配列番号に、-1 を返すようにしています。
892                 *
893                 * @param       table     DBTableModel  一覧が格納されているDBTableModel
894                 * @param       nameArray       カラム名配列
895                 * @return      カラムNo配列(カラム名が存在しない場合は、-1)
896                 */
897        //      private int[] getTableColumnNo( final DBTableModel table ,final String[] nameArray ) {
898        //              int[] clmNo = new int[ nameArray.length ];
899        //              for( int i=0; i<clmNo.length; i++ ) {
900        //                      clmNo[i] = table.getColumnNo( nameArray[i] , false );   // カラム名が存在しない場合は、-1 を返す。
901        //              }
902        //              return clmNo;
903        //      }
904
905                
906                /**
907                 * フォルダを作成します。
908                 *
909                 * フォルダが存在しない場合は、途中階層をすべて作成します。
910                 *
911                 * @og.rev 5.10.9.0 (2019/03/01) クラウドストレージ対応を追加。
912                 * 
913                 * @param       fname   フォルダ名
914                 * @param       createDir       ターゲットとなるフォルダがなければ、作成するかどうか(true:作成する)
915                 * @param  storageType ターゲットとなるストレージタイプ
916                 * @param  bucketName   ターゲットとなるバケット名
917                 * 
918                 * @return File フォルダを表すファイルオブジェクト。引数が null の場合は、null を返します。
919                 * @throws      HybsSystemException             ファイルか、存在しない場合に、createDir=false か、mkdirs() が false の場合
920                 */
921                private File mkDirs( final String fname , final boolean createDir, final String storageType, final String bucketName ) {
922                        File target = null;
923                        if( fname != null ) {
924                                // 5.10.9.0 (2019/03/01) MODIFY  FileをFileOperateInterfaceに置き換え
925//                              target = new File( fname );
926                                target = HybsFileOperationFactory.create(storageType, bucketName, fname);
927                                if( target.exists() ) {                 // 存在する
928                                        if( target.isFile() ) {
929                                                String errMsg = "ターゲットに、ファイル名は指定できません。" + HybsSystem.CR
930                                                                                        + "ターゲット=[" + fname + "]"  + HybsSystem.CR;
931                                                throw new HybsSystemException( errMsg );
932                                        }
933                                }
934                                else {                                                  // 存在しない
935                                        // 存在しないのに、作成しない
936                                        if( !createDir ) {
937                                                String errMsg = "ターゲットが存在しません。 " + HybsSystem.CR
938                                                                                        + "ターゲット=[" + fname + "]"  + HybsSystem.CR;
939                                                throw new HybsSystemException( errMsg );
940                                        }
941                                        // 作成できない
942                                        if( !target.mkdirs() ) {
943                                                String errMsg = "ターゲットを自動作成使用としましたが、作成できませんでした。" + HybsSystem.CR
944                                                                                        + "ターゲット=[" + fname + "]"  + HybsSystem.CR;
945                                                throw new HybsSystemException( errMsg );
946                                        }
947                                }
948                        }
949                        return target;
950                }
951        }
952
953        /**
954         * シリアライズ用のカスタムシリアライズ書き込みメソッド
955         *
956         * @og.rev 4.0.0.0 (2006/09/31) 新規追加
957         * @serialData 一部のオブジェクトは、シリアライズされません。
958         *
959         * @param       strm    ObjectOutputStreamオブジェクト
960         * @throws IOException  シリアライズに関する入出力エラーが発生した場合
961         */
962        private void writeObject( final ObjectOutputStream strm ) throws IOException {
963                strm.defaultWriteObject();
964        }
965
966        /**
967         * シリアライズ用のカスタムシリアライズ読み込みメソッド
968         *
969         * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。
970         *
971         * @og.rev 4.0.0.0 (2006/09/31) 新規追加
972         * @serialData 一部のオブジェクトは、シリアライズされません。
973         *
974         * @param       strm    ObjectInputStreamオブジェクト
975         * @see #release2()
976         * @throws IOException  シリアライズに関する入出力エラーが発生した場合
977         * @throws ClassNotFoundException       クラスを見つけることができなかった場合
978         */
979        private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException {
980                strm.defaultReadObject();
981        }
982
983        
984        /**
985         * このオブジェクトの文字列表現を返します。
986         * 基本的にデバッグ目的に使用します。
987         * 
988         * @og.rev 5.10.9.0 (2019/03/01) fromStorageType,fromBucketName,toStorageType,toBucketNameを追加。
989         * 
990         * @return このクラスの文字列表現
991         */
992        @Override
993        public String toString() {
994                return org.opengion.fukurou.util.ToString.title( this.getClass().getName() )
995                                .println( "VERSION"                     ,VERSION                )
996                                .println( "action"                      ,action                 )
997                                .println( "command"                     ,command                )
998                                .println( "targetDir"           ,targetDir              )
999                                .println( "createDir"           ,createDir              )
1000                                .println( "tableId"                     ,tableId                )
1001                                .println( "outMessage"          ,outMessage     )
1002                                .println( "displayMsg"          ,displayMsg     )
1003                                .println( "selectedAll"         ,selectedAll    )
1004                                .println( "keepTimeStamp"       ,keepTimeStamp  )
1005                                .println( "fromStorageType"     ,fromStorageType        )
1006                                .println( "fromBucketName"      ,fromBucketName         )
1007                                .println( "toStorageType"       ,toStorageType          )
1008                                .println( "toBucketName"                ,toBucketName           )
1009                                .fixForm().toString() ;
1010        }
1011}