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