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);
}
}
