Java API Client

Java's main strength is that it uses a bytecode runtime so that it is portable amongst many platforms.

You can download the fully working NetBeans project here.

SmartFileException.java

package smartfileapi;

// A simple Exception class that can handle the HTTP
// status.
public class SmartFileException extends Exception {
    private int status = 0;

    public SmartFileException(String error, int status) {
        super(error);
        this.status = status;
    }

    @Override
    public String toString() {
        return this.getMessage();
    }

    public int getStatus() {
        return this.status;
    }
}

SmartFileAPI.java

package smartfileapi;

import java.net.*;
import java.io.BufferedReader;
import java.io.OutputStreamWriter;
import java.io.InputStreamReader;
import java.util.Hashtable;
import java.util.Enumeration;
import org.xml.sax.XMLReader;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.XMLReaderFactory;

public class SmartFileAPI {
    // These constants are needed to access the API.
    private static String API_URL = "http://app.smartfile.com/api/1";
    private static String API_KEY = "api-key";
    private static String API_PWD = "api-password";

    // This function does the bulk of the work by performing
    // the HTTP request and raising an exception for any HTTP
    // status code other than 201.
    private static void httpRequest(String uri, Hashtable<String, String> data, String method) throws Exception {
        // We use the XML format because Java has no native JSON decoder.
        String url = String.format("%s%s?format=xml", API_URL, uri);
        Authenticator.setDefault(new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication (API_KEY, API_PWD.toCharArray());
            }
        });
        URL opener = new URL(url);
        HttpURLConnection conn = (HttpURLConnection)opener.openConnection();
        conn.addRequestProperty("User-Agent", "Java SmartFile API Sample Client");
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        conn.setUseCaches(false);
        conn.setDoInput(true);
        conn.setRequestMethod(method);
        if (method.equals("POST")) {
            conn.setDoOutput(true);
            String pre = "";
            StringBuilder post = new StringBuilder();
            Enumeration keys = data.keys();
            while (keys.hasMoreElements()) {
                String key = (String)keys.nextElement();
                String value = URLEncoder.encode(data.get(key), "utf-8");
                post.append(String.format("%s%s=%s", pre, key, value));
                pre = "&";
            }
            conn.setRequestProperty("Content-Length", String.valueOf(post.length()));
            OutputStreamWriter requestStream = new OutputStreamWriter(conn.getOutputStream());
            requestStream.write(post.toString());
            requestStream.flush();
            requestStream.close();
        }
        int status = conn.getResponseCode();
        if (status == 201)
            // Success, return.
            return;
        // Non-201 status code, parse message and throw an Exception.
        BufferedReader responseStream = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
        responseStream.mark(1024);
        StringBuffer responseString = new StringBuffer(1024);
        char[] buf = new char[1024];
        int bytes = 0;
        while((bytes = responseStream.read(buf)) != -1) {
            responseString.append(String.valueOf(buf, 0, bytes));
        }
        String message = responseString.toString();
        try {
            responseStream.reset();
            XMLReader xr = XMLReaderFactory.createXMLReader();
            XmlMessageParser handler = new XmlMessageParser();
            xr.setContentHandler(handler);
            xr.setErrorHandler(handler);
            xr.parse(new InputSource(responseStream));
            message = handler.getMessage();
        }
        catch (Exception e) {
            throw e;
        }
        finally {
            responseStream.close();
        }
        throw new SmartFileException(message, status);
    }

    // This function makes the User add API call. It uses the httpRequest
    // function to handle the transport. Additional API calls could be supported
    // simply by writing additional wrappers that create the data Hashtable and
    // use httpRequest to do the grunt work.
    public static void CreateUser(String fullname, String username, String password, String email) throws Exception {
        Hashtable<String, String> data = new Hashtable();
        data.put("name", fullname);
        data.put("username", username);
        data.put("password", password);
        data.put("email", email);
        httpRequest("/users/add/", data, "POST");
    }
}

Main.java

package smartfileapi;

import java.util.Scanner;

public class Main {
    private static Scanner scan = new Scanner(System.in);

    // A simple method to ask the user a question and
    // return their response.
    private static String prompt(String prompt) {
         System.out.print(prompt);
         return scan.nextLine();
    }

    // Get things started in main()
    public static void main(String[] args) {
        // Ask the user for the required parameters. These will be
        // passed to the API via an HTTP POST request.
         String fullname = prompt("Please enter a full name: ");
         String username = prompt("Please enter a username: ");
         String password = prompt("Please enter a password: ");
         String email = prompt("Please enter an email address: ");
         try {
             // Try to create the new user...
            SmartFileAPI.CreateUser(fullname, username, password, email);
            System.out.println(String.format("Successfully created user %s.", username));
         }
         catch (Exception e) {
             // Print the error message from the server on failure.
             System.out.println(String.format("Error creating User %s: %s.", username, e.toString()));
         }
    }

}

XmlMessageParser.java

package smartfileapi;

import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.Attributes;

// A quick and dirty SAX XML parser to get the API response
// message when an error occurs.
public class XmlMessageParser extends DefaultHandler {
    private boolean inMessage = false;
    private String message = null;

    public XmlMessageParser()
    {
        super();
    }

    public String getMessage()
    {
        return this.message;
    }

    @Override
    public void startElement(String uri, String name,
                             String qName, Attributes atts) {
        if (name.equals("message"))
            this.inMessage = true;
    }

    @Override
    public void endElement(String uri, String name, String qName) {
        if (this.inMessage && name.equals("message"))
            this.inMessage = false;
    }

    @Override
    public void characters(char ch[], int start, int length) {
        if (!this.inMessage)
            return;
        this.message = new String(ch, start, length);
    }
}