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.fukurou.process;
017    
018    import org.opengion.fukurou.util.Argument;
019    import org.opengion.fukurou.util.FTPConnect;
020    import org.opengion.fukurou.util.LogWriter;
021    
022    import java.util.Map ;
023    import java.util.LinkedHashMap ;
024    
025    import java.io.File;
026    
027    /**
028     * Process_FileFtp は、上流から受け取っ?FileLineModel を??る?
029     * ChainProcess インターフェースの実?ラスです?
030     *
031     * 上流から受け取っ?FileLineModel の ファイルから、localPath のローカル共通パス?
032     * remotePath のFTP共通パスに、PFT伝?します?(-command=PUT 処??み)
033     * ファイルそ?も?の階層構?は、維持されるため、ローカルからFTPサーバ?
034     * へのフォル?ピ?に近いイメージになります?
035     *
036     * Process_FileCopy との違いは、ファイルのエンコード変換は行いません。た??
037     * FTP伝?での改行コード?変換は?mode=ASCII で?できます?
038     * もうひとつ、Process_FileCopy では、inPath と outPath でのCOPY処?したが?
039     * こ?クラスでは、localPath と、remotePath でそれぞれの共通パスを指定します?
040     *
041     * 上流?ロセスでは、Name 属?として、?File』を持ち、?は、Fileオブジェク?
042     * である、Process_FileSearch を使用するのが?便利です?それ以外?クラス?
043     * 使用する場合でも?Name属?と、File オブジェクトを持つ LineModel を受け渡?
044     * できれば、使用可能です?
045     *
046     * 引数??中に空白を含??合?、ダブルコー??ション("") で括って下さ??
047     * 引数??の ?』?前後には、空白は挟めません。??key=value の様に
048     * 繋げてください?
049     *
050     * @og.formSample
051     *  Process_FileFtp -host=FTPサーバ? -user=ユーザー -pass=パスワー?-localPath=ローカル共通パス -remotePath=FTP共通パス
052     *                   [-mode=[ASCII/BINARY]  ] [-passive=[true/false] ]
053     *
054     *    -host=FTPサーバ?             ?FTPサーバ?
055     *    -user=ユーザー                ?ユーザー
056     *    -pass=パスワー?             ?パスワー?
057     *    -localPath=ローカル共通パス   ?上流で検索されたファイルパスのローカル側共通部?
058     *    -remotePath=FTP共通パス       ?上流で検索されたファイルパスのFTP側共通部?
059     *   [-mode=[ASCII/BINARY]  ]       ?扱?ァイルの種類を?しま?初期値:ASCII)
060     *   [-passive=[true/false] ]       ?パ?ブモー?ローカルからサーバ?へ接続を張?を利用するかど?(初期値:true)
061     *                                      (false:アク?ブモー?通常のFTPの初期値)で通信します?)
062     *   [-mkdirs=[true/false]  ]       ?受け?ファイル(GET?LOCAL、PUT?FTPサーバ?)に?レクトリを作?するかど?(初期値:true)
063     *                                      (false:?レクトリが無ければ、エラーにします?)
064     *   [-encode=エンコード名 ]        ?日本語ファイル名などのエンコード名を指定しま?初期値:UTF-8)
065     *   [-timeout=タイ?ウ?秒] ]   ?Dataタイ?ウ?初期値:600 [秒])
066     *   [-display=[false/true] ]       ?trueは、検索状況を表示しま?初期値:false)
067     *   [-debug=[false|true]   ]       ?デバッグ??を標準?力に表示する(true)かしな?false)?初期値:false[表示しない])
068     *
069     * @og.rev 5.1.5.0 (2010/04/01) 新規追?
070     *
071     * ※ 注?
072     *    Windwosにおいて、大量ファイルのFTP伝?を行う場合?、注意が?です?
073     *    Windowsにおけるソケ?の?値は?000がデフォルト?です?
074     *    また?TIME_WAITの?ォルト?は??=240?です?
075     *    FTPの様に??タ伝?時に毎回、ソケ?を作?すると、?ートが枯?ます?
076     *
077     *    こ?値を変更するには、レジストリに以下?キーを設定する?があります?
078     *
079     *    ?ケ?の?数(5,000??5,534の間で設???
080     *    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\MaxUserPort (DWORD)
081     *
082     *    ?IME_WAITの時間(30??00秒?間で設???
083     *    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\TcpTimedWaitDelay (DWORD)
084     *
085     *    ※ 設定後?再起動しな?設定が反映されません?
086     *
087     * @version  4.0
088     * @author   Kazuhiko Hasegawa
089     * @since    JDK5.0,
090     */
091    public class Process_FileFtp extends AbstractProcess implements ChainProcess {
092            private static final int     TIMEOUT = 600 ;    // Dataタイ?ウ?初期値:600 [秒])
093    
094            private FTPConnect      ftp                     = null;
095    //      private File            tempFile        = null;
096    
097            private String  host            = null;                 // FTPサーバ?
098            private String  user            = null;                 // ユーザー
099    //      private String  pass            = null;                 // パスワー?
100            private String  command         = "PUT";                // FTPサーバ?側での処??方?GET/PUT/DEL)を指定します?(PUTのみ固?
101            private String  localPath       = null;                 // 上流で検索されたファイルパスのローカル側共通部?
102            private String  remotePath      = null;                 // 上流で検索されたファイルパスのFTP側共通部?
103    
104            private boolean display         = false;                // trueは、検索状況を表示しま?初期値:false)
105            private boolean debug           = false;                // ????を標準?力に表示する(true)かしな?false)?
106    
107            private int     localPathLen    = 0;
108            private int     inCount                 = 0;
109    
110            private static final Map<String,String> mustProparty   ;          // ?プロパティ???チェ?用 Map
111            private static final Map<String,String> usableProparty ;          // ?プロパティ?整合?チェ? Map
112    
113            private static final String[] MODE_LST = new String[] { "ASCII","BINARY" };
114    //      private static final String[] CMD_LST  = new String[] { "GET","PUT","DEL" };
115    
116            static {
117                    mustProparty = new LinkedHashMap<String,String>();
118                    mustProparty.put( "host",               "接続?のFTPサーバ?のアドレスまた?、サーバ????)" );
119                    mustProparty.put( "user",               "接続するユーザー???)" );
120                    mustProparty.put( "pass",               "接続するユーザーのパスワー???)" );
121                    mustProparty.put( "localPath",  "上流で検索されたファイルパスのローカル側共通部???)" );
122                    mustProparty.put( "remotePath", "上流で検索されたファイルパスのFTP側共通部???)" );
123    
124                    usableProparty = new LinkedHashMap<String,String>();
125                    usableProparty.put( "mode",                     "扱?ァイルの種?ASCII/BINARY)を指定しま?初期値:ASCII)" );
126            //      usableProparty.put( "command",          "FTPサーバ?側での処??方?GET/PUT/DEL)を指定しま?初期値:PUT)" );
127                    usableProparty.put( "passive",          "パッシブモー?ローカルからサーバ?へ接続を張?を利用するかど?(初期値:true)" );
128                    usableProparty.put( "mkdirs",           "受け側ファイル(GET?LOCAL、PUT?FTPサーバ?)に?レクトリを作?するかど?(初期値:true)" );
129                    usableProparty.put( "encode",           "日本語ファイル名などのエンコード名を指定しま?初期値:UTF-8)" );
130                    usableProparty.put( "timeout",          "Dataタイ?ウ?初期値:600 [秒])" );
131                    usableProparty.put( "display",          "[false/true]:trueは、検索状況を表示しま?初期値:false)" );
132                    usableProparty.put( "debug",            "????を標準?力に表示する(true)かしな?false)? +
133                                                                                            CR + "(初期値:false:表示しな?" );
134            }
135    
136            /**
137             * ?ォルトコンストラクター?
138             * こ?クラスは、動??されます??ォルトコンストラクターで?
139             * super クラスに対して、?な初期化を行っておきます?
140             *
141             */
142            public Process_FileFtp() {
143                    super( "org.opengion.fukurou.process.Process_FileFtp",mustProparty,usableProparty );
144            }
145    
146            /**
147             * プロセスの初期化を行います?初めに??、呼び出されます?
148             * 初期処?ファイルオープン??オープン?に使用します?
149             *
150             * @param   paramProcess ??タベ?スの接続???などを持って?オブジェク?
151             */
152            public void init( final ParamProcess paramProcess ) {
153                    Argument arg = getArgument();
154    
155    //              String host = arg.getProparty( "host");                         // FTPサーバ?
156    //              String user = arg.getProparty( "user" );                        // ユーザー
157                    String pass = arg.getProparty( "pass" );                        // パスワー?
158                    host = arg.getProparty( "host");                        // FTPサーバ?
159                    user = arg.getProparty( "user" );                       // ユーザー
160    //              pass = arg.getProparty( "pass" );                       // パスワー?
161    
162                    ftp = new FTPConnect();
163    
164                    ftp.setHostUserPass( host , user , pass );
165    
166                    // localPath と、remotePath をセ?します?
167                    localPath       = arg.getProparty("localPath" );
168                    remotePath      = arg.getProparty("remotePath" );
169    
170                    localPathLen  = localPath.length();
171    
172                    // FTP処??な?パラメータをセ?します?
173                    ftp.setMode(    arg.getProparty( "mode"         ,"ASCII",MODE_LST       ));             // 扱?ァイルの種類を?します?
174    //              ftp.setCommand( "PUT"                                                                                    );             // FTP処??方法を?します?
175                    ftp.setPassive( arg.getProparty( "passive"      ,true                           ));             // パッシブモードを利用するかど?
176                    ftp.setMkdirs(  arg.getProparty( "mkdirs"       ,true                           ));             // 受け側ファイルに?レクトリを作?するかど?
177                    ftp.setEncode(  arg.getProparty( "encode"       ,"UTF-8"                        ));             // 日本語ファイル名などのエンコード名を指定しま?初期値:UTF-8)
178                    ftp.setTimeout( arg.getProparty( "timeout"      ,TIMEOUT                        ));             // Dataタイ?ウ?初期値:600 [秒])
179    
180                    display = arg.getProparty("display",display);
181                    debug   = arg.getProparty("display",debug);
182    
183                    ftp.setDisplay( display );              // trueは、検索状況を表示します?(初期値:false)
184                    ftp.setDebug(   debug   );              // ????を標準?力に表示する(true)かしな?false)?
185    
186                    // FTPConnect を?期化します?
187                    ftp.connect();
188            }
189    
190            /**
191             * プロセスの終?行います??に??、呼び出されます?
192             * 終???ファイルクローズ??クローズ?に使用します?
193             *
194             * @param   isOK ト?タルで、OK?たかど?[true:成功/false:失敗]
195             */
196            public void end( final boolean isOK ) {
197                    if( ftp != null ) {
198                            ftp.disconnect();
199                    }
200            }
201    
202            /**
203             * 引数の LineModel を??るメソ?です?
204             * 変換処?? LineModel を返します?
205             * 後続??行わな?????タのフィルタリングを行う場?は?
206             * null ??タを返します?つまり?null ??タは、後続??行わな?
207             * フラグの代わりにも使用して?す?
208             * なお?変換処?? LineModel と、オリジナルの LineModel が?
209             * 同?、コピ?(クローン)か?、各処?ソ??決めて?す?
210             * ドキュメントに明記されて???合?、副作用が問題になる?合??
211             * ???とに自?コピ?(クローン)して下さ??
212             *
213             * @param       data    オリジナルのLineModel
214             *
215             * @return      処?換後?LineModel
216             */
217            public LineModel action( final LineModel data ) {
218                    inCount++ ;
219                    final FileLineModel fileData ;
220                    if( data instanceof FileLineModel ) {
221                            fileData = (FileLineModel)data ;
222                    }
223                    else {
224                            // LineModel ?FileLineModel でな??合?オブジェクトを作?します?
225                            fileData = new FileLineModel( data );
226                    }
227    
228                    File localFile = fileData.getFile() ;   // LineModel から取得したファイル?
229                    if( ! localFile.isFile() ) {
230                            if( display ) { println( data.dataLine() ); }
231                            return data;
232                    }
233    
234                    String lclFileName = localFile.getAbsolutePath();
235    
236                    // ファイル名?、引数ファイル?から?localPathを引き、remotePath を加えます?
237                    String rmtFileName = remotePath + lclFileName.substring( localPathLen );
238    
239    //              ftp.setLocalFile(       lclFileName );                                  // ローカルのファイル?
240    //              ftp.setRemoteFile(      rmtFileName );                                  // FTP先?ファイル?
241    
242                    ftp.action( command,lclFileName,rmtFileName );
243    
244                    if( display ) { println( data.dataLine() ); }
245                    return data ;
246            }
247    
248            /**
249             * プロセスの処?果のレポ?ト表現を返します?
250             * 処??ログラ?、?力件数、?力件数などの??です?
251             * こ???をそのまま、標準?力に出すことで、結果レポ?トと出来るよ?
252             * 形式で出してください?
253             *
254             * @return   処?果のレポ??
255             */
256            public String report() {
257                    String report = "[" + getClass().getName() + "]" + CR
258                                    + TAB + "Copy Count : " + inCount   + CR
259                                    + TAB + "host       : " + host      + CR
260                                    + TAB + "user       : " + user      + CR
261                                    + TAB + "localPath  : " + localPath + CR
262                                    + TAB + "remotePath : " + remotePath ;
263    
264                    return report ;
265            }
266    
267            /**
268             * こ?クラスの使用方法を返します?
269             *
270             * @return      こ?クラスの使用方?
271             */
272            public String usage() {
273                    StringBuilder buf = new StringBuilder();
274    
275                    buf.append( "Process_FileFtp は、上流から受け取っ?FileLineModel を???                                  ).append( CR );
276                    buf.append( "ChainProcess インターフェースの実?ラスです?"                                                                      ).append( CR );
277                    buf.append( CR );
278                    buf.append( "上流から受け取っ?FileLineModel の ファイルから、localPath のローカル共通パス?   ).append( CR );
279                    buf.append( "remotePath のFTP共通パスに、PFT伝?します?(-command=PUT 処??み) "                             ).append( CR );
280                    buf.append( "ファイルそ?も?の階層構?は、維持されるため、ローカルからFTPサーバ?"                               ).append( CR );
281                    buf.append( "へのフォル?ピ?に近いイメージになります?"                                                                            ).append( CR );
282                    buf.append( CR );
283                    buf.append( "Process_FileCopy との違いは、ファイルのエンコード変換は行いません。た??               ).append( CR );
284                    buf.append( "FTP伝?での改行コード?変換は?mode=ASCII で?できます?"                                               ).append( CR );
285                    buf.append( "もうひとつ、Process_FileCopy では、inPath と outPath でのCOPY処?したが?"             ).append( CR );
286                    buf.append( "こ?クラスでは、localPath と、remotePath でそれぞれの共通パスを指定します?"                ).append( CR );
287                    buf.append( CR );
288                    buf.append( "上流?ロセスでは、Name 属?として、?File』を持ち、?は、Fileオブジェク?                    ).append( CR );
289                    buf.append( "である、Process_FileSearch を使用するのが?便利です?それ以外?クラス?                   ).append( CR );
290                    buf.append( "使用する場合でも?Name属?と、File オブジェクトを持つ LineModel を受け渡?          ).append( CR );
291                    buf.append( "できれば、使用可能です?"                                                                                                                    ).append( CR );
292                    buf.append( CR ).append( CR );
293    
294                    buf.append( getArgument().usage() ).append( CR );
295    
296                    return buf.toString();
297            }
298    
299            /**
300             * こ?クラスは、main メソ?から実行できません?
301             *
302             * @param       args    コマンド引数配?
303             */
304            public static void main( final String[] args ) {
305                    LogWriter.log( new Process_FileFtp().usage() );
306            }
307    }