2012/02/19

Very simple ftp client library

Holy moly! It's been almost a year since my last post. I won't go into the typical moaning...."been uber-busy, personal stuff, whatever...." (who cares).

Yet another ftp client....

Thing is, the other day I had to automate the release process of one of our projects made in Java. Thus, using Ant to do it, everything went fine 'til the point where I had to upload some contents to a FTP server we have. Main issues is that this server we have has certificate signed by a non-trusted authority. Well, actually it is signed by a trusted CA (StartSSL), but for some reason I never managed to discover, my openjdk jvm does not like it.

When trying to connect using SSH and checking certificate the default X509TrustManager basically won't let you finish the SSL handshake. This a very recurrent and well known issue with two possible solutions. First and most simple is to simply import the certificate to your keystore using the keytool command. Instructions for how to do this are all over google, but to make things easier, check here.

The bad thing about this approach is that you have to do this for every machine you want to run the app. The other option is to implement your own X509TrustManager, which allows you to "bypass" the server certificate procedure if you require so.

ftp4j 

Now in the ant file that was being created, I tried to use the existing FTP task avalilable (check here), but I never managed to make it work, probably because it does not support FTPES, exactly what our server is using. The combination of both issues made me thought...why I don't implement my own FPT client? I checked existing FTP libraries in Java because I didn't wanted to reinvent the wheel....just a wrapper with very simple client functionalities with server certificate "bypassing" possibilites. I required an OpenSource library because I wanted to make this OpenSource too and also because hey! I like OpenSource :P. After some research found ftp4j (check it here), a very nice library that had all the features required:

  • OpenSource
  • Easy to use
  • FTP, FTPS and most important, FTPES features included
  • Easy way to include custom server certificate checking
The library I made is a simple wrapper around ftp4j library, with only a subset of the typical FPT tasks, which include:

  • Connect
  • Disconnect
  • Login
  • Upload file
  • Download file
  • Delete file
  • Upload directory
  • Download directory
  • Delete file
  • Delete directory
Let's try it out
    The library is ultra-simple to use (that was what kept in mind all the time). Once included in your classpath, you first must setup the client:

    import org.ftp.simpleclient.FtpClient;
    import org.ftp.simpleclient.FtpClient.secure;
    
    /**
     * Main 
     * 
     * @param args
     */
    public static void main(String[] args) {
      
        FtpClient client = new FtpClient();
        client.setBypass(true);
        client.setConnectionType(secure.FTPES);
        client.setHost("my.ftp.server");
        client.setPort(21);
        client.setUser("user");
        client.setPassword("password");
    }
    
    All parameters are mandatory and a brief explanation follows:

    • bypass: If true tell the client that it must accept the server certificate no matter what. I recommed this only if you own the server you are connecting to or you know is a trusted one.
    • connectionType: tells the client the type of server. Possible values are FTP, FTPS and FTPES.
    • host: server address or IP.
    • port: server listening port.
    • user: user name. If trying an anonymous login, "anonymous" must be specified as user name.
    • password: user password. If trying an anonymous login, type a random password, althoug some servers require an email address.
    Once the client is configured, you can connect to the server:

    client.connect();
    

    Mostly all methods return true or false depending on operation success, so you can control the flow of your application. Once connected, you must login, even if you're using an anonymous login:

    if (client.connect()){
       client.login();
    }
    

    If logged in successfully, typical FTP operations can be done very simply, let's see a test program:

    String jarDir = "scripts/lib";
    String uploadFile = "scripts/lib/foo";
    String getDir = "adk/lib/java/test";
    String downloadDir = "scripts/downloads";
    String destDir = "adk";
      
    //setup client
    if (client.setupClient()){
        //try to connect
        if (client.connect()){
        //try to login
     if (client.login()){
         //try to upload a full directory
         client.uploadDirFiles(jarDir, destDir);
         //try to upload a single file   
         if (client.uploadFile(uploadFile, getDir)){
      //now download the file, just for fun!
      if (client.downloadFile("foo", getDir, downloadDir{    
          //try to delete a full directory
          if (client.deleteDir(getDir)){
                            //if success, disconnect
              if (client.disconnect()){
           return;
       }
          }
      }
         } 
     }
        }
    }  
    


    Well, tha'ts all!, I'll write about how to make a custom ant task and how to use this library in the custom task for the next article. I've uploaded the project to google code, so you can check it out (keep reading...).

    NOTE: I've migrated to GitHub...Google code is a real pain in the ass these days, thus, moving to GitHub or something like Bitbucket seems the only choice now. Here is the new link in GitHub.

    Happy coding! :D

    No comments:

    Post a Comment