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.util;
017    
018    import java.io.File;
019    import java.io.IOException;
020    
021    /**
022     * AbstractConnect.java は、å?通的に使用されã‚?ファイル伝é?関連の基本機è?を実è£?�—たã?Abstractクラスですã?
023     *
024     * -host=サーバã? -user=ユーザー -passwd=パスワーãƒ?-remoteFile=接続å?のファイルå�?をå¿??設定しますã?
025     * -localFile=ローカルのファイル名ã?、å¿??ではありませんがã?-command=DEL の場合にのみ不要でありã€?
026     * それ以外ã? command の場合ã?、å¿?¦�ですã?
027     *
028     * -command=[GET/PUT/DEL/GETDIR/PUTDIR/DELDIR] は、サーバã?に対しての処ç�??方法をæŒ?®šしますã?
029     *   GET:サーバã?からローカルにファイル転送しまã�?初期値)
030     *   PUT:ローカルファイルをサーバã?に PUT(STORE、SAVE、UPLOAD、などと同意èª?しますã?
031     *   DEL:サーバã?のæŒ?®šã?ファイルを削除しますã?こã?場合ã?みã€?localFile 属æ?のæŒ?®šã?不要ですã?
032     *   GETDIR,PUTDIR,DELDIR:æŒ?®šã?フォルãƒ?»¥下ã?ファイルをå?ç�?�—ますã?
033     *
034     * -mkdirs=[true/false] は、受けå?のファイル(GETæ™?LOCAL、PUTæ™?サーバã?)に取り込ã‚?ƒ•ァイルのãƒ?‚£レクトリã�?
035     * 存在しなã�??合に、作æ?するかどã�?�‹を指定しまã�?初期値:true)
036     * 通常、サーバã?に、フォルãƒ?šŽ層を作æ?してPUTする場合ã?動的にフォルãƒ?šŽ層を作æ?したã�?‚±ースで便利ですã?
037     * é€?�«、フォルãƒ??確定しており、指定フォルãƒ?»¥外に PUT するのはバグってã�?‚‹と事がåˆ?�‹ってã�?‚‹場合には
038     * false に設定して、存在しなã�?ƒ•ォルãƒ?�«PUT しよã�?�¨すると、エラーになるよã�?�«しますã?
039     *
040     * 引数æ–?­—å?中に空白を含ã‚??合ã?、ダブルコーãƒ??ション("") で括って下さã�??
041     * 引数æ–?­—å?の ã€?』ã?前後には、空白は挟めません。å¿?�šã€?key=value の様に
042     * 繋げてくださいã€?
043     *
044     * @og.formSample
045     *  XXXConnect -host=サーバã? -user=ユーザー -passwd=パスワーãƒ?-remoteFile=接続å?のファイルå�?[-localFile=ローカルのファイル名]
046     *                   [-command=[GET/PUT/DEL/GETDIR/PUTDIR/DELDIR] ] [-display=[true/false] ] ・・・・
047     *
048     *    -host=サーバã?                    ?š接続å?のサーバã?のアドレスまたã?、サーバã?å�?
049     *    -user=ユーザー                    ?š接続するユーザーå�?
050     *    -passwd=パスワーãƒ?               ?š接続するユーザーのパスワーãƒ?
051     *    -remoteFile=接続å?のファイルå�?   ?š接続å?のサーバã?側のファイル名ã?PUT,GET 関係なくFTP側としてæŒ?®šしますã?
052     *   [-localFile=ローカルのファイル名]  ?šローカルのファイル名ã?PUT,GET 関係なくローカルファイルを指定しますã?
053     *   [-port=ポã?ãƒ?]                    ?š接続するサーバã?のポã?トをæŒ?®šしますã?
054     *   [-command=[GET/PUT/DEL] ]          ?šサーバã?側での処ç�??方法をæŒ?®šしますã?
055     *             [GETDIR/PUTDIR/DELDIR]]          GET:FTP⇒LOCAL、PUT:LOCAL⇒FTP への転送でã�?初期値:GET)
056     *                                              DEL:FTPファイルを削除しますã?
057     *                                              GETDIR,PUTDIR,DELDIR æŒ?®šã?フォルãƒ?»¥下ã?ファイルをå?ç�?�—ますã?
058     *   [-mkdirs=[true/false]  ]           ?š受けå?ファイル(GETæ™?LOCAL、PUTæ™?サーバã?)にãƒ?‚£レクトリを作æ?するかどã�?�‹(初期値:true)
059     *                                              (false:ãƒ?‚£レクトリが無ければ、エラーにしますã?)
060     *   [-encode=エンコード名 ]            ?š日本語ファイル名などのエンコード名を指定しまã�?初期値:Windows-31J)
061     *   [-timeout=タイãƒ?‚¢ウãƒ?秒] ]       ?šDataタイãƒ?‚¢ウãƒ?初期値:600 [秒])
062     *   [-display=[false/true] ]           ?štrueは、検索状況を表示しまã�?初期値:false)
063     *   [-debug=[false|true]   ]           ?šデバッグæƒ??を標準å?力に表示する(true)かしなã�?false)ã�?初期値:false[表示しない])
064     *
065     * @og.rev 5.1.6.0 (2010/05/01) 新規追åŠ?
066     *
067     * @version  5.0
068     * @author       Kazuhiko Hasegawa
069     * @since    JDK5.0,
070     */
071    public abstract class AbstractConnect implements ConnectIF {
072            public static final String CR = System.getProperty("line.separator");
073            private final StringBuilder errMsg = new StringBuilder( 200 );
074    
075            /** 正常フラグ  {@value} */
076            public static final boolean FLAG_OK = true;
077            /** 異常フラグ  {@value} */
078            public static final boolean FLAG_NG = false;
079            /** Dataタイãƒ?‚¢ウãƒ?初期値:{@value} [秒]) */
080            public static final int         TIMEOUT = 600 ;
081    
082            /** サーバã? */
083            protected String        host            = null;                 // サーバã?
084            /** ユーザー */
085            protected String        user            = null;                 // ユーザー
086            /** パスワーãƒ?*/
087            protected String        passwd          = null;                 // パスワーãƒ?
088            /** ポã?ãƒ?*/
089            protected String        port            = null;                 // ポã?ãƒ?
090    
091            /** ãƒ?‚£レクトリを作æ?するかどã�?�‹ */
092            protected boolean       isMkdirs        = true;                 // 受け側ファイルにãƒ?‚£レクトリを作æ?するかどã�?�‹。true:作æ?する / false:無ければエラー
093            /** Dataタイãƒ?‚¢ウãƒ? */
094            protected int           timeout         = TIMEOUT;              // Dataタイãƒ?‚¢ウãƒ?初期値:600 [秒])
095            /** 検索状況を表示するかどã�?�‹  */
096            protected boolean       isDisplay       = false;                // trueは、検索状況を表示しまã�?初期値:false)
097            /** ãƒ?ƒ�ãƒ?‚°æƒ??を表示するかどã�?�‹  */
098            protected boolean       isDebug         = false;                // ãƒ?ƒ�ãƒ?‚°æƒ??を標準å?力に表示する(true)かしなã�?false)ã�?
099    
100            /**
101             * サーバã?への接続ã?ログインを行いますã?
102             */
103            @Override
104            public abstract void connect() ;
105    
106            /**
107             * command , localFile , remoteFile をå?に、FTP処ç�?‚’行いますã?
108             *
109             * こã?メソãƒ?ƒ‰は、connect( String , String , String )メソãƒ?ƒ‰、およã?ã€?
110             * paramInit() 実行後に、呼び出すå¿?¦�がありますã?
111             *
112             * @param       command GET:HOST⇒LOCAL 、PUT:LOCAL⇒HOST 、DEL:HOSTファイルを削除
113             * @param       localFile       ローカルのファイルå�?
114             * @param       remoteFile      HOST接続å?のファイルå�?
115             * @throws RuntimeException
116             */
117            @Override
118            public void action( final String command, final String localFile, final String remoteFile ) {
119                    String rmtFile = remoteFile.replace( '\\','/' );
120                    if( isDisplay ) {
121                            System.out.println( "ACTION: command=" + command + ",localFile=" + localFile + ",remoteFile=" + rmtFile );
122                    }
123    
124                    try {
125                            // 実際の処ç�?‚’行いますã?(GET/PUT/DEL)
126                            if( "GET".equals( command ) ) {
127                                    actionGET( localFile, rmtFile );
128                            }
129                            else if( "PUT".equals( command ) ) {
130                                    actionPUT( localFile, rmtFile );
131                            }
132                            else if( "DEL".equals( command ) ) {
133                                    actionDEL( rmtFile );
134                            }
135                            else if( "GETDIR".equals( command ) ) {
136                                    actionGETdir( localFile, rmtFile );
137                            }
138                            else if( "PUTDIR".equals( command ) ) {
139                                    actionPUTdir( localFile, rmtFile );
140                            }
141                            else if( "DELDIR".equals( command ) ) {
142                                    actionDELdir( rmtFile );
143                            }
144                            else {
145                                    errAppend( "commandは、GET/PUT/DEL/GETDIR/PUTDIR/DELDIR からæŒ?®šくã�?�•ã�??" );
146                                    errAppend( "   command    = [" , command , "]" );
147                                    throw new RuntimeException(  getErrMsg() );
148                            }
149                    }
150                    catch( Exception ex ) {
151                            errAppend( "Server action Error." );
152                            errAppend( "   command    = [" , command        , "]" );
153                            errAppend( "   localFile  = [" , localFile      , "]" );
154                            errAppend( "   remoteFile = [" , remoteFile , "]" );
155                            errAppend( ex.getMessage() );
156                            if( isDebug ) { ex.printStackTrace(); }
157                            throw new RuntimeException( getErrMsg(),ex );
158                    }
159            }
160    
161            /**
162             * サーバã?との接続をクローズしますã?
163             *
164             * ログインされてã�?‚‹場合ã?、ログアウトも行いますã?
165             * コネクトされてã�?‚‹場合ã?、ディスコネクトしますã?
166             */
167            @Override
168            public abstract void disconnect();
169    
170            /**
171             * command="GET" が指定されたときã?処ç�?‚’行いますã?
172             *
173             * 接続å?のサーバã?側のファイル名をローカルにãƒ?‚¦ンロードしますã?
174             *
175             * @param       localFile       ローカルのファイルå�?
176             * @param       remoteFile      接続å?のファイルå�?
177             * @throws Exception
178             */
179            protected abstract void actionGET( final String localFile, final String remoteFile ) throws Exception ;
180    
181            /**
182             * command="GETDIR" が指定されたときã?処ç�?‚’行いますã?
183             *
184             * 接続å?のサーバã?側のãƒ?‚£レクトリ以下をローカルãƒ?‚£レクトリに階層構é?のままãƒ?‚¦ンロードしますã?
185             *
186             * @param       localDir        ローカルのãƒ?‚£レクトリå�?
187             * @param       remoteDir       接続å?のãƒ?‚£レクトリå�?
188             * @throws IOException
189             */
190            protected abstract void actionGETdir( final String localDir, final String remoteDir ) throws Exception ;
191    
192            /**
193             * command="PUT" が指定されたときã?処ç�?‚’行いますã?
194             *
195             * ローカルファイルをã?接続å?のサーバã?側にアãƒ??ロードしますã?
196             *
197             * @param       localFile       ローカルのファイルå�?
198             * @param       remoteFile      接続å?のファイルå�?
199             * @throws Exception
200             */
201            protected abstract void actionPUT( final String localFile, final String remoteFile ) throws Exception ;
202    
203            /**
204             * command="PUTDIR" が指定されたときã?処ç�?‚’行いますã?
205             *
206             * ローカルファイルのãƒ?‚£レクトリ以下を、接続å?のサーバã?側のãƒ?‚£レクトリに階層構é?のままアãƒ??ロードしますã?
207             *
208             * @og.rev 5.3.7.0 (2011/07/01) フォルãƒ?�«アクセスできなã�??合ã?、エラーを返しますã?
209             *
210             * @param       localDir        ローカルのãƒ?‚£レクトリå�?
211             * @param       remoteDir       接続å?のãƒ?‚£レクトリå�?
212             * @throws Exception
213             */
214            protected void actionPUTdir( final String localDir, final String remoteDir ) throws Exception {
215                    File[] lclFiles = new File( localDir ).listFiles();
216    
217                    // 5.3.7.0 (2011/07/01) フォルãƒ?�«アクセスできなã�??合ã?、エラーを返しますã?
218                    if( lclFiles == null ) {
219                            errAppend( "æŒ?®šã?ãƒ?‚£レクトリは、アクセスできませんã€? );
220                            errAppend( "   localDir   = [" , localDir       , "]" );
221                            throw new RuntimeException( getErrMsg() );
222                    }
223    
224                    for( int i=0; i<lclFiles.length; i++ ) {
225                            String lcl = lclFiles[i].getName();
226                            if( lclFiles[i].isDirectory() ) {
227                                    actionPUTdir( addFile( localDir,lcl ),addFile( remoteDir,lcl ) );
228                            }
229                            else {
230                                    actionPUT( addFile( localDir,lcl ),addFile( remoteDir,lcl ) );
231                            }
232                    }
233            }
234    
235            /**
236             * command="DEL" が指定されたときã?処ç�?‚’行いますã?
237             *
238             * 接続å?のサーバã?側のファイル名を削除しますã?
239             *
240             * @param       remoteFile      接続å?のファイルå�?
241             * @throws Exception
242             */
243            protected abstract void actionDEL( final String remoteFile ) throws Exception ;
244    
245            /**
246             * command="DELDIR" が指定されたときã?処ç�?‚’行いますã?
247             *
248             * 接続å?のサーバã?側のãƒ?‚£レクトリ名を削除しますã?
249             *
250             * @param       remoteDir       接続å?のãƒ?‚£レクトリå�?
251             * @throws Exception
252             */
253            protected abstract void actionDELdir( final String remoteDir ) throws Exception ;
254    
255            /**
256             * ローカルファイルのãƒ?‚£レクトリを作æ?しますã?
257             *
258             * 引数のファイル名ã?、ファイル名ですã?作æ?するãƒ?‚£レクトリは、そのファイルオブジェクトã?
259             * getParentFile() で取得されるãƒ?‚£レクトリまでを作æ?しますã?
260             *
261             * @param       localFile       ローカルのファイルå�?
262             * @throws IOException , RuntimeException
263             */
264            protected void makeLocalDir( final String localFile ) throws IOException {
265                    File fileDir = new File( localFile ).getCanonicalFile().getParentFile();
266                    if( !fileDir.exists() ) {
267                            if( ! fileDir.mkdirs() ) {
268                                    errAppend( "ローカルファイルのãƒ?‚£レクトリの作æ?に失敗しましたã€? );
269                                    errAppend( "   localFile   = [" , localFile     , "]" );
270                                    throw new RuntimeException( getErrMsg() );
271                            }
272                    }
273            }
274    
275            /**
276             * ãƒ?‚£レクトリとファイル名を合æ?しますã?
277             *
278             * 単純に、ディレクトリのæœ?¾Œと、ファイルのæœ??のã€?/" をチェãƒ?‚¯しã?
279             * 存在すれば、そのまま、結合しã?存在しなければã€?/" を追åŠ?�—ますã?
280             * 両方に存在する場合ã?、片方をã?ずしますã?
281             *
282             * @param       dir     ãƒ?‚£レクトリå�?
283             * @param       file    ファイルå�?
284             *
285             * @return      合æ?されたファイルå�?
286             */
287            protected String addFile( final String dir,final String file ) {
288                    final String filepath ;
289    
290                    char ch1 = dir.charAt( dir.length()-1 ) ;       // ãƒ?‚£レクトリのæœ?¾Œã?æ–?­?
291                    char ch2 = file.charAt( 0 ) ;                           // ファイルのæœ??のæ–?­?
292    
293                    if( ch1 == '/' || ch1 == '\\' ) {
294                            if( ch2 == '/' || ch2 == '\\' ) {       // 両方とも存在するã€?
295                                    filepath = dir + file.substring(1);
296                            }
297                            else {
298                                    filepath = dir + file;
299                            }
300                    }
301                    else {
302                            if( ch2 == '/' || ch2 == '\\' ) {       // ç‰?–¹のみ存在するã€?
303                                    filepath = dir + file;
304                            }
305                            else {
306                                    filepath = dir + "/" + file;
307                            }
308                    }
309    
310                    return filepath ;
311            }
312    
313            /**
314             * サーバã?の、ã?ストã?ユーザー、パスワードを設定しますã?
315             *
316             * @param       host    サーバã?
317             * @param       user    ユーザー
318             * @param       passwd  パスワーãƒ?
319             */
320            @Override
321            public void setHostUserPass( final String host , final String user , final String passwd ) {
322                    this.host = host;
323                    this.user = user;
324                    this.passwd = passwd;
325            }
326    
327            /**
328             * サーバã?名を取得しますã?
329             *
330             * @return      サーバã?
331             */
332    //      protected String getHost() { return host; }
333    
334            /**
335             * ユーザー名を取得しますã?
336             *
337             * @return      ユーザー
338             */
339    //      protected String getUser() { return user; }
340    
341            /**
342             * パスワードを取得しますã?
343             *
344             * @return      パスワーãƒ?
345             */
346    //      protected String getPassword() { return passwd; }
347    
348            /**
349             * 接続に利用するポã?ト番号を設定しますã?
350             *
351             * @param       port    接続に利用するポã?ト番号
352             */
353            @Override
354            public void setPort( final String port ) {
355                    if( port != null ) {
356                            this.port = port ;
357                    }
358            }
359    
360            /**
361             * ポã?トを取得しますã?
362             * 設定されてã�?‚‹生ã?port属æ?(nullもありうã‚?を返しますã?
363             *
364             * @return      ポã?ãƒ?
365             */
366            protected String getPort() { return port; }
367    
368            /**
369             * ポã?トを取得しますã?
370             * 設定されてã�?‚‹port属æ?がã?nullの場合ã?、defPortを返しますã?
371             *
372             * @param       defPort port ã�?null の場合ã?初期値
373             *
374             * @return      ポã?ãƒ?
375             */
376            protected int getPort( final int defPort) {
377                    return ( port == null ) ? defPort : Integer.parseInt( port );
378            }
379    
380            /**
381             * それぞれの受け側ファイルにãƒ?‚£レクトリを作æ?するかどã�?�‹(初期値:true:作æ?する)ã€?
382             *
383             * -mkdirs=[true/false] は、受けå?のファイル(GETæ™?LOCAL、PUTæ™?サーバã?)に取り込ã‚?ƒ•ァイルのãƒ?‚£レクトリã�?
384             * 存在しなã�??合に、作æ?するかどã�?�‹を指定しまã�?初期値:true)
385             * 通常、サーバã?に、フォルãƒ?šŽ層を作æ?してPUTする場合ã?動的にフォルãƒ?šŽ層を作æ?したã�?‚±ースで便利ですã?
386             * é€?�«、フォルãƒ??確定しており、指定フォルãƒ?»¥外に PUT するのはバグってã�?‚‹と事がåˆ?�‹ってã�?‚‹場合には
387             * false に設定して、存在しなã�?ƒ•ォルãƒ?�«PUT しよã�?�¨すると、エラーになるよã�?�«しますã?
388             *
389             * @param       isMkdirs        受け側ファイルにãƒ?‚£レクトリを作æ?するかどã�?�‹。true:作æ?する
390             */
391            @Override
392            public void setMkdirs( final boolean isMkdirs ) {
393                    this.isMkdirs = isMkdirs ;
394            }
395    
396            /**
397             * 受け側ファイルにãƒ?‚£レクトリを作æ?するかどã�?�‹を取得しますã?
398             *
399             * @return      受け側ファイルにãƒ?‚£レクトリを作æ?するかどã�?�‹。true:作æ?する
400             */
401    //      protected boolean isMkdirs() { return isMkdirs; }
402    
403            /**
404             * タイãƒ?‚¢ウトを秒でæŒ?®šしまã�?初期値:600 [秒])ã€?
405             *
406             * オリジナルの FTPClient#setDataTimeout( int ) は、ミリ秒でセãƒ?ƒˆ
407             * しますが、ここã?メソãƒ?ƒ‰では、秒でセãƒ?ƒˆしますã?
408             *
409             * @param       timeout タイãƒ?‚¢ウãƒ?秒]
410             * @throws RuntimeException タイãƒ?‚¢ウトã?æŒ?®šが大きすぎた場å�?
411             */
412            @Override
413            public void setTimeout( final int timeout ) {
414                    if( Integer.MAX_VALUE / 1000 < timeout ) {
415                            errAppend( "タイãƒ?‚¢ウトã?æŒ?®šが大きすぎますã?" );
416                            errAppend( "   timeout   = [" , timeout , "]" );
417                            throw new RuntimeException( getErrMsg() );
418                    }
419    
420                    this.timeout = timeout ;
421            }
422    
423            /**
424             *æŒ?®šされたタイãƒ?‚¢ウトを秒で取得しまã�?初期値:600 [秒])ã€?
425             *
426             * @return      タイãƒ?‚¢ウãƒ?秒]
427             */
428    //      protected int getTimeout() { return timeout; }
429    
430            /**
431             * 実行状況ã?表示可否 を設定しまã�?初期値:false:表示しなã�?ã€?
432             *
433             * @param       isDisplay       実行状況ã?表示可否
434             */
435            @Override
436            public void setDisplay( final boolean isDisplay ) {
437                    this.isDisplay = isDisplay ;
438            }
439    
440            /**
441             * 実行状況ã?表示可否を取得しますã?
442             *
443             * @return      実行状況ã?表示可否
444             */
445    //      protected boolean isDisplay() { return isDisplay; }
446    
447            /**
448             * ãƒ?ƒ�ãƒ?‚°æƒ??の表示可否 を設定しまã�?初期値:false:表示しなã�?ã€?
449             *
450             * @param       isDebug ãƒ?ƒ�ãƒ?‚°æƒ??の表示可否
451             */
452            @Override
453            public void setDebug( final boolean isDebug ) {
454                    this.isDebug = isDebug ;
455            }
456    
457            /**
458             * ãƒ?ƒ�ãƒ?‚°æƒ??の表示可否 を取得しますã?
459             *
460             * @return      ãƒ?ƒ�ãƒ?‚°æƒ??の表示可否
461             */
462    //      protected boolean isDebug() { return isDebug; }
463    
464            /**
465             * 処ç�?¸­に発生したエラーメãƒ?‚»ージをセãƒ?ƒˆしますã?
466             *
467             * @param       msg  メãƒ?‚»ージ化したいオブジェクãƒ?
468             */
469            protected void errAppend( final Object msg ) {
470                    errMsg.append( String.valueOf(msg) ).append( CR );
471            }
472    
473            /**
474             * 処ç�?¸­に発生したエラーメãƒ?‚»ージをセãƒ?ƒˆしますã?
475             *
476             * @param       msgs  Object...
477             */
478            protected void errAppend( final Object... msgs ) {
479                    for( int i=0; i<msgs.length; i++ ) {
480                            errMsg.append( String.valueOf(msgs[i]) );
481                    }
482    
483                    errMsg.append( CR );
484            }
485    
486            /**
487             * 処ç�?¸­に発生したエラーメãƒ?‚»ージを取りå?しますã?
488             *
489             * @return      エラーメãƒ?‚»ージ
490             */
491            @Override
492            public String getErrMsg() {
493                    return errMsg.toString();
494            }
495    }