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.fukurou.util;
017
018import java.io.FileInputStream;
019import java.io.FileOutputStream;
020import java.io.InputStream;
021import java.io.OutputStream;
022import java.io.PrintWriter;
023import java.io.IOException;
024import java.util.Map;
025import java.util.LinkedHashMap ;
026import java.time.Duration;                                                                      // 8.4.1.0 (2023/02/10)
027
028import org.opengion.fukurou.system.OgRuntimeException ;         // 6.4.2.0 (2016/01/29)
029import org.apache.commons.net.ftp.FTP;
030import org.apache.commons.net.ftp.FTPClient;
031import org.apache.commons.net.ftp.FTPFile;
032import org.apache.commons.net.PrintCommandListener;
033import org.apache.commons.net.ftp.FTPReply;
034
035import org.opengion.fukurou.system.Closer;                                                      // 6.4.2.0 (2016/01/29) package変更 fukurou.util → fukurou.system
036import org.opengion.fukurou.system.ThrowUtil;                           // 6.4.2.0 (2016/01/29) package変更 fukurou.util → fukurou.system
037
038/**
039 * FTPConnect.java は、共通的に使用される FTP関連の基本機能を実装した、クラスです。
040 *
041 * これは、org.apache.commons.net.ftp.FTPClient をベースに開発されています。
042 * このクラスの実行には、commons-net-ftp-2.0.jar が必要です。
043 *
044 * -host=FTPサーバー -user=ユーザー -passwd=パスワード -remoteFile=FTP先のファイル名 を必須設定します。
045 * -localFile=ローカルのファイル名は、必須ではありませんが、-command=DEL の場合にのみ不要であり、
046 * それ以外の command の場合は、必要です。
047 *
048 * -mode=[ASCII/BINARY] は、ファイル転送時に、ファイルの種類によって指定します。
049 * ASCIIモードは、OS毎に異なる改行コードを変換して転送します。BINARYモードは、そのままの姿でやり取りします。
050 *
051 * -command=[GET/PUT/DEL] は、FTPサーバーに対しての処理の方法を指定します。
052 *   GET:FTPサーバーからローカルにファイル転送します(初期値)。
053 *   PUT:ローカルファイルをFTPサーバーに PUT(STORE、SAVE、UPLOAD、などと同意語)します。
054 *   DEL:FTPサーバーの指定のファイルを削除します。この場合のみ、-localFile 属性の指定は不要です。
055 *
056 * -passive=[true/false] は、パッシブモード(ローカルからサーバーへ接続を張る)を利用する場合に宣言します。
057 * 初期値は、true:使用する です。
058 * 通常のFTPでは、アクティブモードでファイルをやり取りします。これは、クライアント側が、サーバーソケットを
059 * オープンし、指定のポートで待ちうけ状態を作り、FTPサーバー側から接続してもらいます。
060 * 一般的な企業内では、ファイアウォールの設定等で、外部からの接続を制限しているケースが多く、アクティブモード
061 * では、繋がらない場合が、ほとんどです。
062 * このクラスでは、初期値をパッシブモードにすることで、企業内のファイアウォールのある環境でも
063 * 接続できるようにしています。
064 *
065 * -mkdirs=[true/false] は、受け側のファイル(GET時:LOCAL、PUT時:FTPサーバー)に取り込むファイルのディレクトリが
066 * 存在しない場合に、作成するかどうかを指定します(初期値:true)。
067 * 通常、FTPサーバーに、フォルダ階層を作成してPUTする場合、動的にフォルダ階層を作成したいケースで便利です。
068 * 逆に、フォルダは確定しており、指定フォルダ以外に PUT するのはバグっていると事が分かっている場合には
069 * false に設定して、存在しないフォルダにPUT しようとすると、エラーになるようにします。
070 *
071 * 引数文字列中に空白を含む場合は、ダブルコーテーション("") で括って下さい。
072 * 引数文字列の 『=』の前後には、空白は挟めません。必ず、-key=value の様に
073 * 繋げてください。
074 *
075 * @og.formSample
076 *  FTPConnect -host=FTPサーバー -user=ユーザー -passwd=パスワード -remoteFile=FTP先のファイル名 [-localFile=ローカルのファイル名]
077 *                   [-mode=[ASCII/BINARY]  ] [-command=[GET/PUT/DEL] ] [-passive=[true/false] ]
078 *
079 *    -host=FTPサーバー                 :接続先のFTPサーバーのアドレスまたは、サーバー名
080 *    -user=ユーザー                    :接続するユーザー名
081 *    -passwd=パスワード                :接続するユーザーのパスワード
082 *    -remoteFile=FTP先のファイル名     :接続先のFTPサーバー側のファイル名。PUT,GET 関係なくFTP側として指定します。
083 *   [-localFile=ローカルのファイル名]  :ローカルのファイル名。PUT,GET 関係なくローカルファイルを指定します。
084 *   [-port=ポート ]                    :接続するサーバーのポートを指定します。
085 *   [-mode=[ASCII/BINARY]  ]           :扱うファイルの種類を指定します(初期値:ASCII)
086 *   [-command=[GET/PUT/DEL] ]          :FTPサーバー側での処理の方法を指定します。
087 *                                              GET:FTP⇒LOCAL、PUT:LOCAL⇒FTP への転送です(初期値:GET)
088 *                                              DEL:FTPファイルを削除します。
089 *   [-passive=[true/false] ]           :パッシブモード(ローカルからサーバーへ接続を張る)を利用するかどうか(初期値:true)
090 *                                              (false:アクティブモード(通常のFTPの初期値)で通信します。)
091 *   [-mkdirs=[true/false]  ]           :受け側ファイル(GET時:LOCAL、PUT時:FTPサーバー)にディレクトリを作成するかどうか(初期値:true)
092 *                                              (false:ディレクトリが無ければ、エラーにします。)
093 *   [-encode=エンコード名 ]            :日本語ファイル名などのエンコード名を指定します(初期値:UTF-8)
094 *   [-timeout=タイムアウト[秒] ]       :Dataタイムアウト(初期値:600 [秒])
095 *   [-display=[false/true] ]           :trueは、検索状況を表示します(初期値:false)
096 *   [-debug=[false|true]   ]           :デバッグ情報を標準出力に表示する(true)かしない(false)か(初期値:false[表示しない])
097 *
098 * @og.rev 5.1.6.0 (2010/05/01) 新規追加
099 *
100 * @version  5.0
101 * @author       Kazuhiko Hasegawa
102 * @since    JDK5.0,
103 */
104public final class FTPConnect extends AbstractConnect {
105        private final FTPClient ftp;
106
107        private static final int DEF_PORT       = 21;   // ポート
108
109        private boolean isAsciiMode = true;                     // 扱うファイルの種類を指定します。             (true:ASCII / false:BINARY)
110        private boolean isPassive       = true;                 // パッシブモードを利用するかどうか。    (true:パッシブ / false:アクティブ)
111        private String  encode          = "UTF-8";              // 日本語ファイル名などのエンコード名(初期値:UTF-8)
112
113        private boolean isConnect       ;                               // コネクト済みかどうか。
114
115        private String  lastRemoteDir = "/";            // FTP先の最後に登録したフォルダ名(mkdir の高速化のため)
116
117        /**
118         * デフォルトコンストラクター
119         *
120         * @og.rev 6.4.1.1 (2016/01/16) PMD refactoring. It is a good practice to call super() in a constructor
121         */
122        public FTPConnect() {
123                super();
124                ftp = new FTPClient();
125        }
126
127        /**
128         * FTPサーバーへの接続、ログインを行います。
129         *
130         * このメソッドは、初期化メソッドです。
131         * FTPサーバーへの接続、ログインを行いますので、複数ファイルを転送する
132         * ケースでは、最初に1度だけ呼び出すだけです。
133         * 接続先を変更する場合は、もう一度このメソッドをコールする必要があります。
134         * (そのような場合は、通常、オブジェクトを構築しなおす方がよいと思います。)
135         *
136         * @og.rev 6.4.2.0 (2016/01/29) ex.printStackTrace() を、ThrowUtil#ogStackTrace(Throwable) に置き換え。
137         */
138        @Override       // AbstractConnect#ConnectIF
139        public void connect() {
140                if( isDisplay ) { System.out.println( "CONNECT: HOST=" + host + ",USER=" + user + ",PORT=" + port ); }
141
142                // もし、すでに接続されていた場合は、クロース処理を行います。
143                if( isConnect ) { disconnect(); }
144
145                try {
146                        // connectメソッドの前に呼び出さなければならないらしい。
147                        // 日本語ファイル名対応(初期値:UTF-8)
148                        if( encode != null ) {
149                                ftp.setControlEncoding( encode );
150                        }
151
152                        // サーバーに対して接続を行います。
153                        ftp.connect( host, getPort( DEF_PORT ) );
154
155                        final int reply = ftp.getReplyCode();
156
157                        if( !FTPReply.isPositiveCompletion( reply ) ) {
158                                errAppend( "FTP server refused connection. [PositiveCompletion]" );
159                                errAppend( "   host    = [" , host      , "]" );
160                                errAppend( "   user    = [" , user      , "]" );
161                                errAppend( "   port    = [" , port      , "]" );
162                                errAppend( ftp.getReplyString() );
163                                disconnect();
164                                throw new OgRuntimeException( getErrMsg() );
165                        }
166
167                        // サーバーに対してログインを行います。
168                        if( !ftp.login( user, passwd ) ) {
169                                errAppend( "ログインに失敗しました。" );
170                                errAppend( "   host    = [" , host      , "]" );
171                                errAppend( "   user    = [" , user      , "]" );
172                                errAppend( "   port    = [" , port      , "]" );
173                                errAppend( ftp.getReplyString() );
174                                disconnect();
175                                throw new OgRuntimeException( getErrMsg() );
176                        }
177
178                        // 各種パラメータを設定します。
179                        paramInit();
180                }
181                catch( final IOException ex ) {
182                        errAppend( "FTP server refused connection." );
183                        errAppend( ftp.getReplyString() );
184                        errAppend( ex );
185                        if( isDebug ) { System.err.println( ThrowUtil.ogStackTrace( ex ) ); }
186                        disconnect();
187                        throw new OgRuntimeException( getErrMsg(),ex );
188                }
189
190                isConnect = true;
191        }
192
193        /**
194         * 設定されたパラメータの初期化処理を行います。
195         *
196         * このメソッドは、ftp.connectt( host )メソッドの実行後に
197         * 呼び出す必要があります。
198         * パラメータを再セット後に、このメソッドを呼び出すことになります。
199         * timeout , encode , CommandListener(display や debug属性) , isPassive ,
200         * isAsciiMode など、ファイル名以外の属性情報の設定を反映させます。
201         * 複数ファイルの転送時には、localFile , remoteFile 属性を設定の上、action() メソッドを
202         * 呼び出すことで、対応できます。
203         *
204         * @throws IOException 入出力エラーが発生したとき
205         */
206        private void paramInit() throws IOException {
207
208                // Dataタイムアウト(初期値:600 [秒])。FTPClient のメソッドには、ミリ秒でセットします。
209//              ftp.setDataTimeout( timeout*1000 );
210                // Dataタイムアウト(初期値:600 [秒]) をセットします。
211                ftp.setDataTimeout( Duration.ofSeconds( timeout) );                                             // 8.4.1.0 (2023/02/10)
212
213                // コマンドリスナーのセット(設定済みのListenerをremoveする実装は、入れてません。)
214                if( isDisplay && isDebug ) {
215                        ftp.addProtocolCommandListener( new PrintCommandListener( new PrintWriter(System.out) ) );
216                }
217
218                // パッシブモードを利用するかどうか。 (true:パッシブ / false:アクティブ)
219                if( isPassive ) { ftp.enterLocalPassiveMode();  }
220                else                    { ftp.enterLocalActiveMode();   }
221
222                // 扱うファイルの種類を指定(true:ASCII / false:BINARY)
223                boolean isOK = FLAG_OK ;
224                if( isAsciiMode ) { isOK = ftp.setFileType( FTP.ASCII_FILE_TYPE ); }
225                else                      { isOK = ftp.setFileType( FTP.BINARY_FILE_TYPE );}
226
227                if( !isOK ) {
228                        errAppend( "paramInit Error." );
229                        errAppend( ftp.getReplyString() );
230                        throw new OgRuntimeException( getErrMsg() );
231                }
232        }
233
234        /**
235         * FTPサーバーとの接続をクローズします。
236         *
237         * ログインされている場合は、ログアウトも行います。
238         * コネクトされている場合は、ディスコネクトします。
239         *
240         * @og.rev 6.4.2.0 (2016/01/29) ex.printStackTrace() を、ThrowUtil#ogStackTrace(Throwable) に置き換え。
241         */
242        @Override       // AbstractConnect#ConnectIF
243        public void disconnect() {
244                if( isDisplay ) { System.out.println( "DISCONNECT:" ); }
245
246                if( isConnect ) {
247                        isConnect = false;
248                        try {
249                                ftp.logout();
250                                if( ftp.isConnected() ) {
251                                        ftp.disconnect();
252                                }
253                        }
254                        catch( final Throwable th ) {
255                                errAppend( "disconnect Error." );
256                                errAppend( ftp.getReplyString() );
257                                errAppend( th );
258                                if( isDebug ) { System.err.println( ThrowUtil.ogStackTrace( th ) ); }                   // 6.4.2.0 (2016/01/29)
259                                throw new OgRuntimeException( getErrMsg(),th );
260                        }
261                }
262        }
263
264        /**
265         * command="GET" が指定されたときの処理を行います。
266         *
267         * 接続先のFTPサーバー側のファイル名をローカルにダウンロードします。
268         *
269         * @param       localFile       ローカルのファイル名
270         * @param       remoteFile      FTP先のファイル名
271         * @throws IOException 入出力エラーが発生したとき
272         */
273        @Override       // AbstractConnect
274        protected void actionGET( final String localFile, final String remoteFile ) throws IOException {
275                if( isDebug ) { System.out.println( "GET: " + remoteFile + " => " + localFile ); }
276
277                // GET(DOWNLOAD)取得時は、ローカルファイルのディレクトリを作成する必要がある。
278                if( isMkdirs ) {
279                        makeLocalDir( localFile );
280                }
281
282        //      InputStream  input  = null;
283                OutputStream output = null;
284                try {
285        //              input  = ftp.retrieveFileStream( remoteFile );  // 連続読み込みを行うと、null になった。
286                        output = new FileOutputStream( localFile );
287        //              isOK = FileUtil.copy( input,output );
288                        if( !ftp.retrieveFile( remoteFile, output ) ) {
289                                errAppend( "ファイルの取得(GET)に失敗しました。" );
290                                errAppend( "   localFile  = [" , localFile      , "]" );
291                                errAppend( "   remoteFile = [" , remoteFile , "]" );
292                                errAppend( ftp.getReplyString() );
293                                throw new OgRuntimeException( getErrMsg() );
294                        }
295                }
296                finally {
297        //              Closer.ioClose( input );
298                        Closer.ioClose( output );
299                }
300        }
301
302        /**
303         * command="GETDIR" が指定されたときの処理を行います。
304         *
305         * 接続先のFTPサーバー側のディレクトリ以下をローカルディレクトリに階層構造のままダウンロードします。
306         *
307         * @param       localDir        ローカルのディレクトリ名
308         * @param       remoteDir       FTP先のディレクトリ名
309         * @throws IOException 入出力エラーが発生したとき
310         */
311        @Override       // AbstractConnect
312        protected void actionGETdir( final String localDir, final String remoteDir ) throws IOException {
313                final FTPFile[] rmtFiles = ftp.listFiles( remoteDir );
314                for( int i=0; i<rmtFiles.length; i++ ) {
315                        final String rmt = rmtFiles[i].getName();
316                        if( rmtFiles[i].isDirectory() ) {
317                                actionGETdir( addFile( localDir,rmt ),addFile( remoteDir,rmt ) );
318                        }
319                        else {
320                                actionGET( addFile( localDir,rmt ),addFile( remoteDir,rmt ) );
321                        }
322                }
323        }
324
325        /**
326         * command="PUT" が指定されたときの処理を行います。
327         *
328         * ローカルファイルを、接続先のFTPサーバー側にアップロードします。
329         *
330         * @param       localFile       ローカルのファイル名
331         * @param       remoteFile      FTP先のファイル名
332         * @throws IOException 入出力エラーが発生したとき
333         */
334        @Override       // AbstractConnect
335        protected void actionPUT( final String localFile, final String remoteFile ) throws IOException {
336                if( isDebug ) { System.out.println( "PUT: " + localFile + " => " + remoteFile ); }
337
338                boolean isOK = FLAG_OK;
339
340                // PUT(UPLOAD)登録時は、リモートファイルのディレクトリを作成する必要がある。
341                if( isMkdirs ) {
342                        // 前回のDIRとの比較で、すでに存在していれば、makeDirectory 処理をパスする。
343                        final int ad = remoteFile.lastIndexOf( '/' ) + 1;                       // 区切り文字を+1する。
344                        final String tmp = remoteFile.substring( 0,ad );
345                        if( ad > 0 && !lastRemoteDir.startsWith( tmp ) ) {
346                                lastRemoteDir = tmp;
347                                if( StringUtil.startsChar( tmp , '/' ) ) {                              // 6.2.0.0 (2015/02/27) 1文字 String.startsWith
348                                        final String[] fls = tmp.split( "/" );
349                                        ftp.changeWorkingDirectory( "/" );
350                                        for( int i=1; i<fls.length; i++ ) {
351                                                isOK = ftp.changeWorkingDirectory( fls[i] );    // まず、チェンジしてみる。
352                                                if( ! isOK ) {
353                                                        isOK = ftp.makeDirectory( fls[i] );                     // チェンジできなければ、作る。
354                                                        if( isOK ) {
355                                                                isOK = ftp.changeWorkingDirectory( fls[i] );    // 作れれば、チェンジする。
356                                                        }
357                                                }
358                                                // チェンジできなければ、エラー
359                                                if( ! isOK ) {
360                                                        errAppend( "チェンジディレクトリに失敗しました。" );
361                                                        errAppend( "   remoteDir  = [" , lastRemoteDir  , "]" );
362                                                        errAppend( ftp.getReplyString() );
363                                                        throw new OgRuntimeException( getErrMsg() );
364                                                }
365                                        }
366                                }
367                                if( ! isOK ) {
368                                        errAppend( "ディレクトリの作成に失敗しました。" );
369                                        errAppend( "   remoteDir  = [" , lastRemoteDir  , "]" );
370                                        errAppend( ftp.getReplyString() );
371                                        throw new OgRuntimeException( getErrMsg() );
372                                }
373                        }
374                }
375
376                InputStream  input  = null;
377        //      OutputStream output = null;
378                try {
379                        input  = new FileInputStream( localFile );
380        //              output = ftp.storeFileStream( remoteFile );
381        //              isOK = FileUtil.copy( input,output );
382                        if( !ftp.storeFile( remoteFile, input ) ) {
383                                errAppend( "ファイルのストア(PUT)に失敗しました。" );
384                                errAppend( "   localFile  = [" , localFile      , "]" );
385                                errAppend( "   remoteFile = [" , remoteFile , "]" );
386                                errAppend( ftp.getReplyString() );
387                                throw new OgRuntimeException( getErrMsg() );
388                        }
389                }
390                finally {
391                        Closer.ioClose( input );
392        //              Closer.ioClose( output );
393                }
394        }
395
396        /**
397         * command="DEL" が指定されたときの処理を行います。
398         *
399         * 接続先のFTPサーバー側のファイル名を削除します。
400         *
401         * @param       remoteFile      FTP先のファイル名
402         * @throws IOException 入出力エラーが発生したとき
403         */
404        @Override       // AbstractConnect
405        protected void actionDEL( final String remoteFile ) throws IOException {
406                if( isDebug ) { System.out.println( "DEL: " + remoteFile ); }
407
408                if( !ftp.deleteFile( remoteFile ) ) {
409                        errAppend( "ファイルの削除(DEL)に失敗しました。" );
410                        errAppend( "   remoteFile = [" , remoteFile , "]" );
411                        errAppend( ftp.getReplyString() );
412                        throw new OgRuntimeException( getErrMsg() );
413                }
414        }
415
416        /**
417         * command="DELDIR" が指定されたときの処理を行います。
418         *
419         * 接続先のFTPサーバー側のディレクトリ名を削除します。
420         *
421         * @param       remoteDir       FTP先のディレクトリ名
422         * @throws IOException 入出力エラーが発生したとき
423         */
424        @Override       // AbstractConnect
425        protected void actionDELdir( final String remoteDir ) throws IOException {
426
427                final FTPFile[] rmtFiles = ftp.listFiles( remoteDir );
428                for( int i=0; i<rmtFiles.length; i++ ) {
429                        final String rmt = addFile( remoteDir,rmtFiles[i].getName() );
430                        if( rmtFiles[i].isDirectory() ) {
431                                actionDELdir( rmt );
432                        }
433                        else {
434                                actionDEL( rmt );
435                        }
436                }
437
438                if( !ftp.removeDirectory( remoteDir ) ) {
439                        errAppend( "Directoryの削除(DEL)に失敗しました。" );
440                        errAppend( "   remoteDir = [" , remoteDir , "]" );
441                        errAppend( ftp.getReplyString() );
442                        throw new OgRuntimeException( getErrMsg() );
443                }
444        }
445
446        /**
447         * 扱うファイルの種類を指定します (初期値:ASCII)。
448         *
449         * ファイルを FTP でやり取りする場合、ASCII 指定すると、OSの改行コードの違いを
450         * 吸収して、ファイルのやり取りが行われます。(つまり、改行コード変換が行われます。)
451         * BINARY 指定すると、現状のファイルのまま、やり取りされます。
452         * これは、たとえ、アスキーファイルであっても、そのままの姿でやり取りされるということです。
453         * 内部的には、isAsciiMode 属性に、true:ASCII / false:BINARY で管理されます。
454         *
455         * @param       mode    扱うファイルの種類を指定します [ASCII/BINARY]
456         */
457        public void setMode( final String mode ) {
458                if( mode != null ) {
459                        if( ! "ASCII".equals( mode ) && ! "BINARY".equals( mode ) ) {
460                                errAppend( "モード指定は、ASCII または、BINARY と指定ください。" );
461                                errAppend( "   mode  = [" , mode        , "]" );
462                                throw new OgRuntimeException( getErrMsg() );
463                        }
464
465                        isAsciiMode = "ASCII".equals( mode ) ;          // "ASCII" 以外は、すべて "BINARY" になる。
466                }
467        }
468
469        /**
470         * パッシブモードを利用するかどうか(true:パッシブ)を設定します(初期値:true)。
471         *
472         * パッシブモード(ローカルからサーバーへ接続を張る)を利用する場合に宣言します。
473         * 通常のFTPでは、アクティブモードでファイルをやり取りします。これは、クライアント側が、サーバーソケットを
474         * オープンし、指定のポートで待ちうけ状態を作り、FTPサーバー側から接続してもらいます。
475         * 一般的な企業内では、ファイアウォールの設定等で、外部からの接続を制限しているケースが多く、アクティブモード
476         * では、繋がらない場合が、ほとんどです。
477         * このクラスでは、初期値をパッシブモードにすることで、企業内のファイアウォールのある環境でも
478         * 接続できるようにしています。
479         *
480         * @param       isPassive       パッシブモードを利用するかどうか。(true:パッシブ)
481         */
482        public void setPassive( final boolean isPassive ) {
483                this.isPassive = isPassive ;
484        }
485
486        /**
487         * 日本語ファイル名などのエンコード名を指定します(初期値:UTF-8)。
488         *
489         * @param       encode  エンコード名
490         */
491        public void setEncode( final String encode ) {
492                if( encode != null ) {
493                        this.encode = encode ;
494                }
495        }
496
497        /**
498         * このクラスの動作確認用の、main メソッドです。
499         *
500         * @param       args    コマンド引数配列
501         */
502        public static void main( final String[] args ) {
503
504                final String[] MODE_LST = new String[] { "ASCII","BINARY" };
505                final String[] CMD_LST  = new String[] { "GET","PUT","DEL","GETDIR","PUTDIR","DELDIR" };
506
507                final Map<String,String> mustProparty   ;               // [プロパティ]必須チェック用 Map
508                final Map<String,String> usableProparty ;               // [プロパティ]整合性チェック Map
509
510                mustProparty = new LinkedHashMap<>();
511                mustProparty.put( "host",               "接続先のFTPサーバーのアドレスまたは、サーバー名(必須)" );
512                mustProparty.put( "user",               "接続するユーザー名(必須)" );
513                mustProparty.put( "passwd",             "接続するユーザーのパスワード(必須)" );
514                mustProparty.put( "remoteFile", "接続先のFTPサーバー側のファイル名(必須)" );
515
516                usableProparty = new LinkedHashMap<>();
517                usableProparty.put( "localFile",        "ローカルのファイル名" );
518                usableProparty.put( "port",                     "接続に利用するポート番号を設定します。" );
519                usableProparty.put( "mode",                     "扱うファイルの種類(ASCII/BINARY)を指定します(初期値:ASCII)" );
520                usableProparty.put( "command",          "FTPサーバー側での処理の方法(GET/PUT/DEL)を指定します(初期値:GET)" );
521                usableProparty.put( "passive",          "パッシブモード(ローカルからサーバーへ接続を張る)を利用するかどうか(初期値:true)" );
522                usableProparty.put( "mkdirs",           "受け側ファイル(GET時:LOCAL、PUT時:FTPサーバー)にディレクトリを作成するかどうか(初期値:true)" );
523                usableProparty.put( "encode",           "日本語ファイル名などのエンコード名を指定します(初期値:UTF-8)" );
524                usableProparty.put( "timeout",          "Dataタイムアウト(初期値:600 [秒])" );
525                usableProparty.put( "display",          "[false/true]:trueは、検索状況を表示します(初期値:false)" );
526                usableProparty.put( "debug",            "デバッグ情報を標準出力に表示する(true)かしない(false)か" +
527                                                                                        CR + "(初期値:false:表示しない)" );
528
529                // ******************************************************************************************************* //
530                //       以下、単独で使用する場合の main処理
531                // ******************************************************************************************************* //
532                final Argument arg = new Argument( "org.opengion.fukurou.util.FTPConnect" );
533                arg.setMustProparty( mustProparty );
534                arg.setUsableProparty( usableProparty );
535                arg.setArgument( args );
536
537                final FTPConnect ftp = new FTPConnect();
538
539                final String host   = arg.getProparty( "host");                 // FTPサーバー
540                final String user   = arg.getProparty( "user" );                        // ユーザー
541                final String passwd = arg.getProparty( "passwd" );              // パスワード
542
543                ftp.setHostUserPass( host , user , passwd );
544
545                ftp.setPort(    arg.getProparty( "port"                                 ) );            // 接続に利用するポート番号を設定します。
546                ftp.setMode(    arg.getProparty( "mode"         ,"ASCII",MODE_LST ) );  // 扱うファイルの種類を指定します。
547                ftp.setPassive( arg.getProparty( "passive"      ,true           ) );            // パッシブモードを利用するかどうか
548                ftp.setMkdirs(  arg.getProparty( "mkdirs"       ,true           ) );            // 受け側ファイルにディレクトリを作成するかどうか
549                ftp.setEncode(  arg.getProparty( "encode"       ,"UTF-8"    ) );                // 日本語ファイル名などのエンコード名を指定します(初期値:UTF-8)
550                ftp.setTimeout( arg.getProparty( "timeout"      ,TIMEOUT    ) );                // Dataタイムアウト(初期値:600 [秒])
551                ftp.setDisplay( arg.getProparty( "display"      ,false          ) );            // trueは、検索状況を表示します(初期値:false)
552                ftp.setDebug(   arg.getProparty( "debug"        ,false          ) );            // デバッグ情報を標準出力に表示する(true)かしない(false)か
553
554                try {
555                        // コネクトします。
556                        ftp.connect();
557
558                        final String command            = arg.getProparty( "command" ,"GET" ,CMD_LST  );        // FTP処理の方法を指定します。
559                        final String localFile  = arg.getProparty( "localFile"  );                                      // ローカルのファイル名
560                        final String remoteFile = arg.getProparty( "remoteFile" );                                      // FTP先のファイル名
561
562                        // command , localFile , remoteFile を元に、SFTP処理を行います。
563                        ftp.action( command,localFile,remoteFile );
564                }
565                catch( final RuntimeException ex ) {
566                        System.err.println( ftp.getErrMsg() );
567                }
568                finally {
569                        // ホストとの接続を終了します。
570                        ftp.disconnect();
571                }
572        }
573}