You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by wo...@apache.org on 2010/09/14 23:57:03 UTC

svn commit: r997113 [1/2] - in /incubator/libcloud/sandbox/java/trunk/src: ./ base/ base/connection/ base/interfaces/ libcloud/ libcloud/data/ libcloud/exceptions/ libcloud/interfaces/ libcloud/providers/ libcloud/providers/amazon/ libcloud/providers/i...

Author: woodser
Date: Tue Sep 14 21:57:01 2010
New Revision: 997113

URL: http://svn.apache.org/viewvc?rev=997113&view=rev
Log:
- Rackspace driver added.
- Refactored structure for simplecloud.
- Miscellaneous fixes & enhancements.

Added:
    incubator/libcloud/sandbox/java/trunk/src/Example.java
    incubator/libcloud/sandbox/java/trunk/src/base/
    incubator/libcloud/sandbox/java/trunk/src/base/Driver.java
    incubator/libcloud/sandbox/java/trunk/src/base/connection/
    incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionKey.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionUserAndKey.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnection.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnectionUserAndKey.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/base/connection/Response.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/base/connection/ResponseHandler.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/base/interfaces/
    incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IConnection.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IResponse.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/libcloud/
    incubator/libcloud/sandbox/java/trunk/src/libcloud/DriverFactory.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/libcloud/NodeDriver.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/libcloud/data/
    incubator/libcloud/sandbox/java/trunk/src/libcloud/data/Node.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeAuth.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeImage.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeLocation.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeSize.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeState.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/libcloud/exceptions/
    incubator/libcloud/sandbox/java/trunk/src/libcloud/exceptions/InvalidCredsException.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/
    incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INode.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INodeDriver.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/
    incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/
    incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2APSEDriver.java
    incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Connection.java
    incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Driver.java
    incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2EUWestDriver.java
    incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Handler.java
    incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2USEastDriver.java
    incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2USWestDriver.java
    incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/
    incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMConnection.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMDriver.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMHandler.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/rackspace/
    incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/rackspace/RackspaceConnection.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/rackspace/RackspaceDriver.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/rackspace/RackspaceHandler.java   (with props)
    incubator/libcloud/sandbox/java/trunk/src/simplecloud/
    incubator/libcloud/sandbox/java/trunk/src/simplecloud/document/
    incubator/libcloud/sandbox/java/trunk/src/simplecloud/queue/
    incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/
    incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/StorageAdapter.java
    incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/StorageFactory.java
    incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/data/
    incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/data/File.java
    incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/data/Folder.java
    incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/data/Item.java
    incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/exceptions/
    incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/exceptions/StorageException.java
    incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/interfaces/
    incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/interfaces/IStorageAdapter.java
    incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/
    incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/amazon/
    incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/amazon/Main.java
    incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/amazon/S3Adapter.java
    incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/amazon/S3Connection.java
    incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/amazon/S3Handler.java
    incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/nirvanix/

Added: incubator/libcloud/sandbox/java/trunk/src/Example.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/Example.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/Example.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/Example.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,55 @@
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import libcloud.DriverFactory;
+import libcloud.NodeDriver;
+import libcloud.DriverFactory.Provider;
+import libcloud.data.NodeImage;
+import libcloud.data.NodeLocation;
+import libcloud.data.NodeSize;
+import libcloud.interfaces.INode;
+import libcloud.providers.amazon.EC2USEastDriver;
+import libcloud.providers.ibm.IBMDriver;
+import libcloud.providers.rackspace.RackspaceDriver;
+
+/*
+ * Illustrates how to interact with multiple cloud providers using a common
+ * interface using Apache libcloud.
+ */
+public class Example {
+
+	/*
+	 * Entry point of execution.
+	 */
+	public static void main(String[] args) {
+		// Fetch driver(s).
+		Class<NodeDriver> ibmClass = DriverFactory.getDriver(Provider.IBM);
+		IBMDriver ibmDriver = (IBMDriver)DriverFactory.constructDriver(ibmClass, "username", "password");
+		Class<NodeDriver> ec2USEastClass = DriverFactory.getDriver(Provider.EC2_US_EAST);
+		EC2USEastDriver ec2USEastDriver = (EC2USEastDriver)DriverFactory.constructDriver(ec2USEastClass, "access key id", "access key");
+		Class<NodeDriver> rackspaceClass = DriverFactory.getDriver(Provider.RACKSPACE);
+		RackspaceDriver rackspaceDriver = (RackspaceDriver)DriverFactory.constructDriver(rackspaceClass, "your username", "your api key");
+		
+		// Insert driver(s) into array for generic processing.
+		List<NodeDriver> drivers = new ArrayList<NodeDriver>();
+		drivers.add(ibmDriver);
+		drivers.add(ec2USEastDriver);
+		drivers.add(rackspaceDriver);
+		
+		// Process drivers.
+		for (NodeDriver driver : drivers) {
+			System.out.println(driver.getName() + ':');
+			List<INode> nodes = driver.listNodes();
+			List<NodeImage> images = driver.listImages();
+			List<NodeSize> sizes = driver.listSizes();
+			List<NodeLocation> locations = driver.listLocations();
+			
+			System.out.println("\t" + nodes.size() + " Nodes: " + nodes);
+			System.out.println("\t" + images.size() + " Images: " + images);
+			System.out.println("\t" + sizes.size() + " Sizes: " + sizes);
+			System.out.println("\t" + locations.size() + " Locations: " + locations);
+		}
+	}
+}

Added: incubator/libcloud/sandbox/java/trunk/src/base/Driver.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/Driver.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/base/Driver.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/base/Driver.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,8 @@
+package base;
+
+import base.interfaces.IConnection;
+
+public class Driver {
+
+	protected IConnection connection;
+}

Added: incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionKey.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionKey.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionKey.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionKey.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,212 @@
+package base.connection;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeSet;
+
+import org.apache.http.HttpEntityEnclosingRequest;
+import org.apache.http.HttpHost;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpPut;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.utils.URIUtils;
+import org.apache.http.client.utils.URLEncodedUtils;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.message.BasicNameValuePair;
+
+import base.Driver;
+import base.interfaces.IConnection;
+
+/*
+ * Manages a connection with a secret access key.
+ */
+public abstract class ConnectionKey implements IConnection {
+
+	protected String host;
+
+	protected int port;
+
+	protected String accessId;
+
+	protected String accessKey;
+
+	protected boolean secure;
+
+	protected Driver driver;
+	
+	protected String method;
+	
+	protected String path;
+
+	protected DefaultHttpClient httpClient;
+
+	protected HttpHost httpHost;
+	
+	public ConnectionKey(String accessKey, boolean secure, String host, Driver driver) {
+		this.accessKey = accessKey;
+		this.secure = secure;
+		this.host = host;
+		this.driver = driver;
+		this.accessId = null;	// subclass may initialize
+		this.port = -1;			// default port used by HTTPComponents
+		this.path = null;
+	}
+
+	public ConnectionKey(String accessKey, boolean secure, String host, int port,
+			Driver driver) {
+		this.accessKey = accessKey;
+		this.secure = secure;
+		this.host = host;
+		this.port = port;
+		this.driver = driver;
+		this.httpClient = null;
+		this.httpHost = null;
+		this.accessId = null;	// subclass may initialize
+		this.path = null;
+	}
+
+	public void connect() {
+		connect(host, port);
+	}
+
+	public void connect(String host, int port) {
+		this.host = host;
+		this.port = port;
+
+		httpClient = new DefaultHttpClient();
+		if (accessId != null) {
+			httpClient.getCredentialsProvider().setCredentials(
+					new AuthScope(host, port),
+					new UsernamePasswordCredentials(accessId, accessKey));
+		}
+	}
+
+	public Response request(String method, String path,
+			Map<String, String> headers, Map<String, String> params, String data) {
+		this.method = method;
+		this.path = path;
+		
+		// Connect if not already connected
+		if (httpClient == null) {
+			connect();
+		}
+		
+		// Compose request headers with priority
+		Map<String, String> reqHeaders = new HashMap<String, String>();
+		reqHeaders.put("User-Agent", getUserAgent());		// 3: libcloud headers
+		reqHeaders.put("Host", host);
+		if (headers != null) reqHeaders.putAll(headers);	// 2: argument headers
+		reqHeaders = addDefaultHeaders(reqHeaders);			// 1: provider headers
+		
+		// Compose request parameters with priority
+		Map<String, String> reqParams = (params != null ? params	// 2: argument parameters
+				: new HashMap<String, String>());
+		reqParams = addDefaultParams(reqParams);					// 1: provider parameters
+
+		// Create URI endpoint
+		URI uri = null;
+		try {
+			String protocol = secure ? "https" : "http";
+			uri = URIUtils.createURI(protocol, host, port, path, urlEncodeMap(reqParams), null);
+		} catch (URISyntaxException e) {
+			e.printStackTrace();
+			return null;
+		}
+		
+		// Create request to send
+		HttpUriRequest request = null;
+		if (method.equalsIgnoreCase("GET")) {
+			request = new HttpGet(uri);
+		} else if (method.equalsIgnoreCase("DELETE")) {
+			request = new HttpDelete(uri);
+		} else if (method.equalsIgnoreCase("PUT")) {
+			request = new HttpPut(uri);
+		} else if (method.equalsIgnoreCase("POST")) {
+			request = new HttpPost(uri);
+		} else {
+			throw new IllegalArgumentException("Illegal HTTP method: " + method);
+		}
+
+		// Encode and add the payload data
+		String encoded = encodeData(data);
+		if (encoded != null && !encoded.equals("")) {
+			try {
+				((HttpEntityEnclosingRequest) request).setEntity(new StringEntity(encoded));
+			} catch (UnsupportedEncodingException e) {
+				e.printStackTrace();
+				return null;
+			}
+		}
+
+		// Add headers to the request
+		for (String header : reqHeaders.keySet()) {
+			request.addHeader(header, reqHeaders.get(header));
+		}
+
+		// Execute the request!
+		try {
+			return new Response(httpClient.execute(request));
+		} catch (ClientProtocolException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+
+		return null; // Error
+	}
+	
+	/*
+	 * Utility that performs UTF-8 encoding of a map of Strings. Returns a
+	 * String that is suitable for use as an application/x-www-form-urlencoded
+	 * list of parameters in an HTTP PUT or HTTP POST.
+	 * 
+	 * @param map is the map of String values to format as a UTF-8 String
+	 * 
+	 * @return String is the UTF-8 encoding of the map of String values
+	 */
+	public static String urlEncodeMap(Map<String, String> map) {
+		if (map == null) return null;
+		
+		// Convert map to List<NameValuePair> for URLEncodedUtils
+		List<BasicNameValuePair> nvp = new ArrayList<BasicNameValuePair>();
+		for (String key : new TreeSet<String>(map.keySet())) {	// preserve order
+			nvp.add(new BasicNameValuePair(key, map.get(key)));
+		}
+		return URLEncodedUtils.format(nvp, "UTF-8");
+	}
+	
+	// ============================ PROTECTED METHODS ===========================
+	protected Map<String, String> addDefaultHeaders(Map<String, String> headers) {
+		return headers;
+	}
+
+	protected Map<String, String> addDefaultParams(Map<String, String> params) {
+		return params;
+	}
+
+	protected String encodeData(String data) {
+		return data;
+	}
+	
+	// ============================ PRIVATE METHODS ===========================
+	/*
+	 * Defines the user agent used when making requests.
+	 * 
+	 * @return String is the user agent for making requests
+	 */
+	private String getUserAgent() {
+		return "libcloud-java";	// TODO: generate version like python?
+	}	
+}

Propchange: incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionKey.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionUserAndKey.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionUserAndKey.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionUserAndKey.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionUserAndKey.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,18 @@
+package base.connection;
+
+import base.Driver;
+
+public class ConnectionUserAndKey extends ConnectionKey {
+
+	public ConnectionUserAndKey(String accessId, String accessKey, boolean secure,
+			String host, int port, Driver driver) {
+		super(accessKey, secure, host, port, driver);
+		this.accessId = accessId;
+	}
+
+	public ConnectionUserAndKey(String accessId, String accessKey, boolean secure,
+			String host, Driver driver) {
+		super(accessKey, secure, host, driver);
+		this.accessId = accessId;
+	}
+}

Propchange: incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionUserAndKey.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnection.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnection.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnection.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnection.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,60 @@
+package base.connection;
+
+import java.util.Map;
+
+import base.Driver;
+
+public class LoggingConnection extends ConnectionKey {
+
+	protected StringBuffer log;
+		
+	public LoggingConnection(String key, boolean secure, String host, int port,
+			Driver driver) {
+		super(key, secure, host, port, driver);
+		log = new StringBuffer();
+	}
+
+	public Response request(String method, String action,
+			Map<String, String> headers, Map<String, String> params, String data) {
+		log.append(logCurl(method, action, data, headers));
+		Response response = super.request(method, action, headers, params, data);
+		log.append(logResponse(response));
+		return response;
+	}
+	
+	protected String logResponse(Response response) {
+		String logEntry = "# -------- begin response ----------\n";
+		logEntry += response.version.getProtocol() + "/" 
+				 + response.version.getMajor() + "." + response.version.getMinor();		
+		logEntry += " " + response.status + " " + response.phrase + "\r\n";
+		
+		if (response.headers != null) {
+			for (Map.Entry<String, String> header : response.headers.entrySet()) {
+			    logEntry += header.getKey() + ": " + header.getValue() + "\r\n";
+			}
+		}
+
+		logEntry += "\r\n" + response.body + "\r\n";
+		logEntry += "\n# -------- end response ------------\n";
+		
+		return logEntry;
+	}
+	
+	protected String logCurl(String method, String url, String body, Map<String, String> headers) {
+		String curl = "curl -X " + method + " ";
+		
+		if (headers != null) {
+			for (Map.Entry<String, String> header : headers.entrySet()) {
+			    curl += "-H \"" + header.getKey() + ": " + header.getValue() + "\" ";
+			}
+		}
+		
+		if (body != null && !"".equals(body)) {
+			curl += "-d \"" + body + "\" ";
+		}
+		
+		curl += url;		
+		return curl;
+	}
+	
+}

Propchange: incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnection.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnectionUserAndKey.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnectionUserAndKey.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnectionUserAndKey.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnectionUserAndKey.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,12 @@
+package base.connection;
+
+import base.Driver;
+
+public class LoggingConnectionUserAndKey extends LoggingConnection {
+
+	public LoggingConnectionUserAndKey(String accessId, String accessKey, boolean secure,
+			String host, int port, Driver driver) {
+		super(accessKey, secure, host, port, driver);
+		this.accessId = accessId;
+	}
+}

Propchange: incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnectionUserAndKey.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/libcloud/sandbox/java/trunk/src/base/connection/Response.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/connection/Response.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/base/connection/Response.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/base/connection/Response.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,96 @@
+package base.connection;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.http.Header;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.ProtocolVersion;
+
+import base.interfaces.IResponse;
+
+
+public class Response implements IResponse {
+	
+	protected int status;
+	
+	protected String phrase;
+	
+	protected String body;
+	
+	protected ProtocolVersion version;
+	
+	protected Map<String, String> headers;
+	
+	public Response(HttpResponse response) {
+		
+		// Retrieve HTTP version from response
+		version = response.getStatusLine().getProtocolVersion();
+		
+		// Retrieve status code from response
+		status = response.getStatusLine().getStatusCode();
+		
+		// Retrieve reason from response
+		phrase = response.getStatusLine().getReasonPhrase();
+		
+		// Retrieve body from response
+		body = null;
+		HttpEntity entity = response.getEntity();
+		if (entity != null) {
+			try {
+				String line = null;
+				StringBuffer bodySb = new StringBuffer();
+				BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent()));
+				while ((line = reader.readLine()) != null) {
+					bodySb.append(line);
+				}
+				body = bodySb.toString();
+				entity.consumeContent();
+			} catch (IOException ioe) {
+				ioe.printStackTrace();
+			}
+		}
+		
+		// Retrieve headers from response
+		headers = new HashMap<String, String>();
+		for (Header header : response.getAllHeaders()) {
+			this.headers.put(header.getName(), header.getValue());
+		}
+	}
+
+	public String getBody() {
+		return body;
+	}
+
+	public ProtocolVersion getVersion() {
+		return version;
+	}
+	
+	public String getPhrase() {
+		return phrase;
+	}
+
+	public Map<String, String> getHeaders() {
+		return headers;
+	}
+
+	public int getStatus() {
+		return status;
+	}
+	
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		sb.append(status + " " + phrase + '\n');
+		sb.append("Headers:\n");
+		for (String key : headers.keySet()) {
+			sb.append('\t' + key + ": " + headers.get(key) + '\n');
+		}
+		sb.append("Body: ");
+		sb.append(body);
+		return sb.toString();
+	}
+}

Propchange: incubator/libcloud/sandbox/java/trunk/src/base/connection/Response.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/libcloud/sandbox/java/trunk/src/base/connection/ResponseHandler.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/connection/ResponseHandler.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/base/connection/ResponseHandler.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/base/connection/ResponseHandler.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,75 @@
+package base.connection;
+
+import base.interfaces.IResponse;
+
+/*
+ * Default handler for request responses.  Subclasses should extend for custom
+ * processing.
+ */
+public class ResponseHandler {
+	
+	protected IResponse response;
+	
+	protected Object object;
+
+	/*
+	 * Constructs the handler with the given response.
+	 * 
+	 * @param response is the request's response
+	 */
+	public ResponseHandler(IResponse response) {
+		this.response = response;
+		
+		if (success()) {
+			parseBody();
+		} else {
+			throw new RuntimeException(parseError());
+		}
+	}
+	
+	/*
+	 * Returns the response's processed representation.
+	 * 
+	 * @return Object is the response's parsed object for additional processing
+	 */
+	public Object getParsedObject() {
+		return object;
+	}
+	
+	/*
+	 * Returns the original response.
+	 * 
+	 * @return IResponse is the request's original response
+	 */
+	public IResponse getResponse() {
+		return response;
+	}
+	
+	/*
+	 * Parses the response's body.  The parsed response is stored in 'object'.
+	 * Subclasses should override for custom processing.
+	 */
+	protected void parseBody() {
+		object = response.getBody();
+	}
+	
+	/*
+	 * Returns a String expressing the error that occurred.  Subclasses should
+	 * override for custom processing.
+	 * 
+	 * @return String represents the error that occurred if !success()
+	 */
+	protected String parseError() {
+		return response.getStatus() + " " + response.getPhrase();
+	}
+	
+	/*
+	 * Indicates if the request was successful or not.  Subclasses should
+	 * override for custom processing.
+	 * 
+	 * @return true if the request was successful, false otherwise
+	 */
+	protected boolean success() {
+		return response.getStatus() >= 200 && response.getStatus() <= 299;
+	}
+}

Propchange: incubator/libcloud/sandbox/java/trunk/src/base/connection/ResponseHandler.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IConnection.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IConnection.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IConnection.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IConnection.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,15 @@
+package base.interfaces;
+
+import java.util.Map;
+
+import base.connection.Response;
+
+public interface IConnection {
+
+	public void connect();
+
+	public void connect(String host, int port);
+	
+	public Response request(String method, String action,
+			Map<String, String> headers, Map<String, String> params, String data);
+}

Propchange: incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IConnection.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IResponse.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IResponse.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IResponse.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IResponse.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,14 @@
+package base.interfaces;
+
+import java.util.Map;
+
+public interface IResponse {
+	
+	public int getStatus();
+	
+	public String getBody();
+	
+	public String getPhrase();
+	
+	public Map<String, String> getHeaders();
+}

Propchange: incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IResponse.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/DriverFactory.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/DriverFactory.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/libcloud/DriverFactory.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/libcloud/DriverFactory.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,128 @@
+package libcloud;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.EnumMap;
+
+/*
+ * Manages provider information and provides a driver factory.
+ */
+public class DriverFactory {
+	
+	// Maps providers to the driver packages.
+	private static EnumMap<Provider, String> providerMap;
+	
+	/*
+	 * List of available drivers.
+	 */
+	public static enum Provider {
+		DUMMY,
+	    EC2_US_EAST,
+	    EC2_US_WEST,
+	    EC2_EU_WEST,
+	    EC2_AP_SOUTHEAST,
+	    ECP,
+	    GOGRID,
+	    RACKSPACE,
+	    SLICEHOST,
+	    VPSNET,
+	    LINODE,
+	    RIMUHOSTING,
+	    VOXEL,
+	    SOFTLAYER,
+	    EUCALYPTUS,
+	    IBM,
+	    OPENNEBULA,
+	    DREAMHOST;
+	}
+	
+	/*
+	 * Initializes the map bewteen providers (enum) and their driver packages.
+	 */
+	private static void initProviderMap()
+	{
+		providerMap = new EnumMap<Provider, String>(Provider.class);
+		
+		//First parameter to the map is the Provider name from the enum, the
+		//second parameter is the package name of the driver.  When adding a new
+		//provider, simply add it to the "Provider" enum and add a providerMap.put
+		//below with the appropriate parameters.
+		providerMap.put(Provider.IBM, "libcloud.providers.ibm.IBMDriver");
+		providerMap.put(Provider.RACKSPACE, "libcloud.providers.rackspace.XXX");
+		providerMap.put(Provider.SLICEHOST, "libcloud.providers.slicehost.XXX");
+		providerMap.put(Provider.EC2_US_EAST, "libcloud.providers.amazon.EC2USEastDriver");
+		providerMap.put(Provider.EC2_EU_WEST, "libcloud.providers.amazon.EC2EUWestDriver");
+		providerMap.put(Provider.EC2_US_WEST, "libcloud.providers.amazon.EC2USWestDriver");
+		providerMap.put(Provider.EC2_AP_SOUTHEAST, "libcloud.providers.amazon.EC2APSoutheastDriver");
+		providerMap.put(Provider.ECP, "");
+		providerMap.put(Provider.GOGRID, "");
+		providerMap.put(Provider.VPSNET, "");
+		providerMap.put(Provider.LINODE, "");
+		providerMap.put(Provider.RIMUHOSTING, "");
+		providerMap.put(Provider.VOXEL, "");
+		providerMap.put(Provider.SOFTLAYER, "");
+		providerMap.put(Provider.EUCALYPTUS, "");
+		providerMap.put(Provider.OPENNEBULA, "");
+		providerMap.put(Provider.DREAMHOST, "");
+	}
+	
+	/*
+	 * Retrieves the driver for the given provider.
+	 * 
+	 * @param p defines the provider to retrieve the driver for
+	 * 
+	 * @return Class<NodeDriver> is the provider's corresponding driver class
+	 */
+	@SuppressWarnings("unchecked")
+	public static Class<NodeDriver> getDriver(Provider p)
+	{
+		if (providerMap == null)
+			initProviderMap();
+		
+		@SuppressWarnings("rawtypes")
+		Class driverClass = null;
+		try {
+			String classname = providerMap.get(p);
+			driverClass = Class.forName(classname).asSubclass(NodeDriver.class);
+		} catch (ClassNotFoundException e) {
+			e.printStackTrace();
+		}
+		return driverClass;
+	}
+	
+	/*
+	 * Constructs a driver from the given driver class and constructor arguments.
+	 * 
+	 * @param driverClass is the class of the driver to construct
+	 * @param args are the arguments to the driver's constructor
+	 * 
+	 * @return NodeDriver is the initialized driver.  Typecast this to the specific driver type.
+	 */
+	public static NodeDriver constructDriver(Class<? extends NodeDriver> driverClass, Object ... args) {
+		// Convert arguments to class array
+		Class<?>[] classArgs = new Class[args.length];
+		for (int i = 0; i < args.length; i++) {
+			classArgs[i] = args[i].getClass();
+		}
+		
+		try {
+			// Get constructor and create instance
+			Constructor<?> constructor = driverClass.getConstructor(classArgs);
+			return (NodeDriver)constructor.newInstance(args);
+		} catch (SecurityException e) {
+			e.printStackTrace();
+		} catch (NoSuchMethodException e) {
+			e.printStackTrace();
+		} catch (IllegalArgumentException e) {
+			e.printStackTrace();
+		} catch (InstantiationException e) {
+			e.printStackTrace();
+		} catch (IllegalAccessException e) {
+			e.printStackTrace();
+		} catch (InvocationTargetException e) {
+			e.printStackTrace();
+		}
+		
+		return null;
+	}
+}

Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/DriverFactory.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/NodeDriver.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/NodeDriver.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/libcloud/NodeDriver.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/libcloud/NodeDriver.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,8 @@
+package libcloud;
+
+import libcloud.interfaces.INodeDriver;
+import base.Driver;
+
+public abstract class NodeDriver extends Driver implements INodeDriver {
+	
+}

Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/NodeDriver.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/Node.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/data/Node.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/libcloud/data/Node.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/libcloud/data/Node.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,85 @@
+package libcloud.data;
+
+import java.util.Map;
+import java.util.UUID;
+
+import libcloud.interfaces.INode;
+import libcloud.interfaces.INodeDriver;
+
+public class Node implements INode {
+	
+	private String id;
+	
+	private String name;
+	
+	private NodeState state;
+	
+	private String publicIp;
+	
+	private String privateIp;
+	
+	private Map<String, Object> extra;
+	
+	private INodeDriver driver;
+	
+	public Node(String id, String name, NodeState state, String publicIp, String privateIp, Map<String, Object> extra, INodeDriver driver) {
+		this.id = id;
+		this.name = name;
+		this.state = state;
+		this.publicIp = publicIp;
+		this.privateIp = privateIp;
+		this.extra = extra;
+		this.driver = driver;
+	}
+
+	public boolean destroy() {
+		return driver.destroyNode(this);
+	}
+
+	public boolean reboot() {
+		return driver.rebootNode(this);
+	}
+
+	public INodeDriver getDriver() {
+		return driver;
+	}
+
+	public Map<String, Object> getExtra() {
+		return extra;
+	}
+
+	public String getId() {
+		return id;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public String getPrivateIp() {
+		return privateIp;
+	}
+
+	public String getPublicIp() {
+		return publicIp;
+	}
+
+	public NodeState getState() {
+		return state;
+	}
+
+	public String getUuid() {
+		return UUID.randomUUID().toString();
+	}
+	
+	public String toString() {
+		return "<Node" +
+		": uuid=" + getUuid() +
+		", id=" + id + 
+		", name=" + name +
+		", state=" + state + 
+		", publicIp=" + publicIp +
+		", driver=" + driver.getName() + 
+		" ...>";
+	}
+}

Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/Node.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeAuth.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeAuth.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeAuth.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeAuth.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,10 @@
+package libcloud.data;
+
+public class NodeAuth {
+
+	public String secret;
+	
+	public NodeAuth(String secret) {
+		this.secret = secret;
+	}
+}

Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeAuth.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeImage.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeImage.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeImage.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeImage.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,31 @@
+package libcloud.data;
+
+import java.util.Map;
+
+import libcloud.interfaces.INodeDriver;
+
+public class NodeImage {
+	
+	public String id;
+	
+	public String name;
+	
+	public Map<String, Object> extra;
+	
+	public INodeDriver driver;
+	
+	public NodeImage(String id, String name, Map<String, Object> extra, INodeDriver driver) {
+		this.id = id;
+		this.name = name;
+		this.extra = extra;
+		this.driver = driver;
+	}
+	
+	public String toString() {
+		return "<NodeImage" +
+		": id=" + id +
+		", name=" + name +
+		", driver=" + driver.getName() + 
+		" ...>";
+	}
+}

Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeImage.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeLocation.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeLocation.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeLocation.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeLocation.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,30 @@
+package libcloud.data;
+
+import libcloud.interfaces.INodeDriver;
+
+public class NodeLocation {
+	
+	public String id;
+	
+	public String name;
+	
+	public String country;
+	
+	public INodeDriver driver;
+	
+	public NodeLocation(String id, String name, String country, INodeDriver driver) {
+		this.id = id;
+		this.name = name;
+		this.country = country;
+		this.driver = driver;
+	}
+
+	public String toString() {
+		return "<NodeLocation" +
+			": id=" + id +
+			", name=" + name +
+			", country=" + country + 
+			", driver=" + driver.getName() + 
+			" ...>";
+	}
+}

Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeLocation.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeSize.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeSize.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeSize.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeSize.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,43 @@
+package libcloud.data;
+
+import libcloud.interfaces.INodeDriver;
+
+public class NodeSize {
+
+	public String id;
+	
+	public String name;
+	
+	public int ram;
+	
+	public int disk;
+	
+	public int bandwidth;
+	
+	public float price;
+	
+	public INodeDriver driver;
+	
+	public NodeSize(String id, String name, int ram, int disk, int bandwidth,
+			float price, INodeDriver driver) {
+		this.id = id;
+		this.name = name;
+		this.ram = ram;
+		this.disk = disk;
+		this.bandwidth = bandwidth;
+		this.price = price;
+		this.driver = driver;
+	}
+	
+	public String toString() {
+		return "<NodeSize" +
+			": id=" + id +
+			", name=" + name +
+			", ram=" + ram + 
+			", disk=" + disk +
+			", bandwidth=" + bandwidth + 
+			", price=" + price +
+			", driver=" + driver.getName() + 
+			" ...>";
+	}
+}

Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeSize.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeState.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeState.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeState.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeState.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,9 @@
+package libcloud.data;
+
+public enum NodeState {
+	RUNNING,
+	REBOOTING,
+	TERMINATED,
+	PENDING,
+	UNKNOWN;
+}

Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeState.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/exceptions/InvalidCredsException.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/exceptions/InvalidCredsException.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/libcloud/exceptions/InvalidCredsException.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/libcloud/exceptions/InvalidCredsException.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,14 @@
+package libcloud.exceptions;
+
+public class InvalidCredsException extends RuntimeException {
+	
+	private static final long serialVersionUID = 1L;
+
+	public InvalidCredsException() {
+		super();
+	}
+	
+	public InvalidCredsException(String msg) {
+		super(msg);
+	}
+}

Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/exceptions/InvalidCredsException.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INode.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INode.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INode.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INode.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,28 @@
+package libcloud.interfaces;
+
+import java.util.Map;
+
+import libcloud.data.NodeState;
+
+public interface INode {
+
+	public boolean reboot();
+	
+	public boolean destroy();
+	
+	public String getUuid();
+	
+	public String getId();
+	
+	public String getName();
+	
+	public NodeState getState();
+	
+	public String getPublicIp();
+	
+	public String getPrivateIp();
+	
+	public INodeDriver getDriver();
+	
+	public Map<String, Object> getExtra();
+}

Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INode.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INodeDriver.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INodeDriver.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INodeDriver.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INodeDriver.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,30 @@
+package libcloud.interfaces;
+
+import java.util.List;
+import java.util.Map;
+
+import libcloud.data.NodeAuth;
+import libcloud.data.NodeImage;
+import libcloud.data.NodeLocation;
+import libcloud.data.NodeSize;
+
+public interface INodeDriver {
+	
+	public INode createNode(String name, NodeSize size,
+			NodeImage image, NodeLocation location, NodeAuth auth,
+			Map<String, Object> extra);
+
+	public boolean destroyNode(INode node);
+
+	public boolean rebootNode(INode node);
+
+	public List<INode> listNodes();
+
+	public List<NodeImage> listImages();
+
+	public List<NodeSize> listSizes();
+
+	public List<NodeLocation> listLocations();
+	
+	public String getName();
+}

Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INodeDriver.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2APSEDriver.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2APSEDriver.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2APSEDriver.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2APSEDriver.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,46 @@
+package libcloud.providers.amazon;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import libcloud.data.NodeLocation;
+
+public class EC2APSEDriver extends EC2Driver {
+	
+	private static final String EC2_AP_SE_HOST = "ec2.ap-southeast-1.amazonaws.com";
+	
+	private static final Map<String, Float> EC2_AP_SE_PRICES = initNodePrices();
+		
+	public EC2APSEDriver(String accessId, String accessKey) {
+		super(accessId, accessKey, EC2_AP_SE_HOST);
+	}
+
+	public List<NodeLocation> listLocations() {
+		List<NodeLocation> locations = new ArrayList<NodeLocation>();
+		locations.add(new NodeLocation("0", "Amazon Asia-Pacific Singapore", "SG", this));
+		return locations;
+	}
+	
+	public String getName() {
+		return "Amazon EC2 (ap-southeast-1)";
+	}
+	
+	protected float getPrice(String sizeId) {
+		return EC2_AP_SE_PRICES.get(sizeId);
+	}
+	
+	private static Map<String, Float> initNodePrices() {
+		Map<String, Float> prices = new HashMap<String, Float>();
+		prices.put("m1.small", .095f);
+		prices.put("m1.large", .38f);
+		prices.put("m1.xlarge", .76f);
+		prices.put("c1.medium", .19f);
+		prices.put("c1.xlarge", .76f);
+		prices.put("m2.xlarge", .57f);
+		prices.put("m2.2xlarge", 1.14f);
+		prices.put("m2.4xlarge", 2.28f);
+		return prices;
+	}
+}

Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Connection.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Connection.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Connection.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Connection.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,77 @@
+package libcloud.providers.amazon;
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SimpleTimeZone;
+import java.util.TreeSet;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.commons.codec.binary.Base64;
+
+import base.Driver;
+import base.connection.ConnectionKey;
+import base.connection.ConnectionUserAndKey;
+
+public class EC2Connection extends ConnectionUserAndKey {
+	
+	private static final boolean DEFAULT_SECURE = true;
+	
+	private static final String API_VERSION = "2010-06-15";
+	
+	public EC2Connection(String accessId, String accessKey, String host,
+			Driver driver) {
+		super(accessId, accessKey, DEFAULT_SECURE, host, driver);
+	}
+	
+	protected Map<String, String> addDefaultParams(Map<String, String> params) {
+		params.put("SignatureVersion", "2");
+		params.put("SignatureMethod", "HmacSHA256");
+		params.put("AWSAccessKeyId", accessId);
+		params.put("Version", API_VERSION);
+		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+		sdf.setTimeZone(new SimpleTimeZone(0, "GMT"));
+		params.put("Timestamp", sdf.format(new Date()));
+		params.put("Signature", getAWSAuthParams(params, accessKey, path));
+		return params;
+	}
+	
+	/*
+	 * Generates the request signature as defined at:
+	 * http://docs.amazonwebservices.com/AWSEC2/2010-06-15/DeveloperGuide/index.html?using-query-api.html
+	 */
+	private String getAWSAuthParams(Map<String, String> params, String accessKey, String path) {
+		// Sort the parameters by key
+		TreeSet<String> sortedKeys = new TreeSet<String>(params.keySet());
+		Map<String, String> sortedParams = new HashMap<String, String>();
+		for (String key : sortedKeys){
+			sortedParams.put(key, params.get(key));
+		}
+		
+		// Generate stringToSign
+		String qs = ConnectionKey.urlEncodeMap(sortedParams);
+		qs = qs.replace("+", "%20");
+		String stringToSign = this.method + '\n' + host + '\n' + path + '\n' + qs;
+		
+		// Calculate HMAC of stringToSign
+		byte[] hmac = null;
+		try {
+			Mac mac = Mac.getInstance("HmacSHA256");
+			SecretKeySpec key = new SecretKeySpec(accessKey.getBytes(), "UTF-8");
+			mac.init(key);
+			hmac = mac.doFinal(stringToSign.getBytes());
+		} catch (NoSuchAlgorithmException e) {
+			e.printStackTrace();
+		} catch (InvalidKeyException e) {
+			e.printStackTrace();
+		}
+		
+		// Base 64 encode HMAC
+		return new String(Base64.encodeBase64(hmac));
+	}
+}

Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Driver.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Driver.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Driver.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Driver.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,404 @@
+package libcloud.providers.amazon;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import libcloud.NodeDriver;
+import libcloud.data.Node;
+import libcloud.data.NodeAuth;
+import libcloud.data.NodeImage;
+import libcloud.data.NodeLocation;
+import libcloud.data.NodeSize;
+import libcloud.data.NodeState;
+import libcloud.interfaces.INode;
+
+import org.apache.commons.codec.binary.Base64;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import base.interfaces.IResponse;
+
+/*
+ * Base driver to interact with Amazon EC2.
+ * 
+ * TODO: comment ec2 classes
+ * TODO: Formal tests of EC2 drivers
+ */
+public abstract class EC2Driver extends NodeDriver {
+	
+	private XPath xpath;
+	protected static final String API_VERSION = "2010-06-15";
+	protected static final String NAMESPACE = "http://ec2.amazonaws.com/doc/" + API_VERSION + "/";
+	private static final Map<String, NodeSize> NODE_SIZES = initNodeSizes();
+	private static final Map<String, NodeState> NODE_STATE_MAP = new HashMap<String, NodeState>();
+	
+	/*
+	 * Constructs the base driver for location-specific drivers to subclass.
+	 * 
+	 * @param accessId is the user's Amazon access key ID
+	 * @param accessKey is the user's Amazon secret key
+	 */
+	public EC2Driver(String accessId, String accessKey, String host) {
+		connection = new EC2Connection(accessId, accessKey, host, this);
+		xpath = XPathFactory.newInstance().newXPath();
+		
+		// Map Amazon EC2 instance states to libcloud
+		NODE_STATE_MAP.put("pending", NodeState.PENDING);
+		NODE_STATE_MAP.put("running", NodeState.RUNNING);
+		NODE_STATE_MAP.put("shutting-down", NodeState.TERMINATED);
+		NODE_STATE_MAP.put("terminated", NodeState.TERMINATED);
+		NODE_STATE_MAP.put("stopping", NodeState.PENDING);
+		NODE_STATE_MAP.put("stopped", NodeState.TERMINATED);
+	}
+
+	/*
+	 * Creates a node on Amazon EC2.
+	 * 
+	 * See http://bit.ly/8ZyPSy [docs.amazonwebservices.com]
+	 * 
+	 * Supported keyword arguments:
+	 * 	ex_mincount: Minimum number of instances to launch
+	 * 	ex_maxcount: Maximum number of instances to launch
+	 * 	ex_securitygroup: Name of security group(s)
+	 * 	ex_keyname: The name of the key pair
+	 * 	ex_userdata: User data
+	 */
+	@SuppressWarnings("unchecked")
+	public INode createNode(String name, NodeSize size, NodeImage image,
+			NodeLocation location, NodeAuth auth, Map<String, Object> extra) {
+		// Add base parameters
+		Map<String, String> params = new HashMap<String, String>();
+		params.put("Action", "RunInstances");
+		params.put("ImageId", image.id);
+		params.put("InstanceType", size.id);
+		params.put("MinCount", "1");
+		params.put("MaxCount", "1");
+		
+		// Process extra map
+		if (extra != null) {
+			// Minimum & Maximum nodes to create
+			if (extra.containsKey("ex_mincount")) {
+				params.put("MinCount", (String)extra.get("ex_mincount"));
+			}
+			if (extra.containsKey("ex_maxcount")) {
+				params.put("MaxCount", (String)extra.get("ex_maxcount"));
+			}
+			
+			// SecurityGroups
+			if (extra.containsKey("ex_securitygroup")) {
+				Object securityGroup = extra.get("ex_securitygroup");
+				List<String> groups = null;
+				if (securityGroup instanceof List) {
+					groups = (List<String>)securityGroup;
+				} else {
+					groups = new ArrayList<String>();
+					groups.add((String)securityGroup);
+				}
+				for (int i = 0; i < groups.size(); i++) {
+					params.put("SecurityGroup." + (i + 1), groups.get(i));
+				}
+			}
+			
+			// KeyName
+			if (extra.containsKey("ex_keyname")) {
+				params.put("KeyName", (String)extra.get("ex_keyname"));
+			}
+			
+			// UserData
+			if (extra.containsKey("ex_userdata")) {
+				String userData = (String)extra.get("ex_userdata");
+				params.put("UserData", new String(Base64.encodeBase64(userData.getBytes())));
+			}
+		}
+		
+		// Send & process request
+		IResponse response = connection.request("GET", "/", null, params, null);
+		EC2Handler handler = new EC2Handler(response);
+		return parseNodes(((Document)handler.getParsedObject()).getDocumentElement(), "instancesSet/item", null).get(0);
+	}
+
+	public boolean destroyNode(INode node) {
+		Map<String, String> params = new HashMap<String, String>();
+		params.put("Action", "TerminateInstances");
+		String[] values = {node.getId()};
+		params.putAll(pathList("InstanceId", values));
+		IResponse response = connection.request("GET", "/", null, params, null);
+		EC2Handler handler = new EC2Handler(response);
+		return parseTerminateBoolean((Document)handler.getParsedObject());
+	}
+
+	public boolean rebootNode(INode node) {
+		Map<String, String> params = new HashMap<String, String>();
+		params.put("Action", "RebootInstances");
+		String[] values = {node.getId()};
+		params.putAll(pathList("InstanceId", values));
+		IResponse response = connection.request("GET", "/", null, params, null);
+		EC2Handler handler = new EC2Handler(response);
+		return parseRebootBoolean(((Document)handler.getParsedObject()));
+	}
+
+	public List<INode> listNodes() {
+		Map<String, String> params = new HashMap<String, String>();
+		params.put("Action", "DescribeInstances");
+		IResponse response = connection.request("GET", "/", null, params, null);
+		EC2Handler handler = new EC2Handler(response);
+		return parseNodesByGroup(((Document)handler.getParsedObject()).getDocumentElement());
+	}
+
+	public List<NodeImage> listImages() {
+		Map<String, String> params = new HashMap<String, String>();
+		params.put("Action", "DescribeImages");
+		IResponse response = connection.request("GET", "/", null, params, null);
+		EC2Handler handler = new EC2Handler(response);
+		return parseImages((Document)handler.getParsedObject());
+	}
+
+	public List<NodeSize> listSizes() {
+		List<NodeSize> sizes = new ArrayList<NodeSize>();
+		for (NodeSize size : NODE_SIZES.values()) {
+			sizes.add(new NodeSize(size.id, size.name, size.ram, size.disk,
+					size.bandwidth, getPrice(size.id), this));
+		}
+		return sizes;
+	}
+	
+	/*
+	 * Creates a new Security Group.
+	 * 
+	 * Note: This is a non-standard extension API and only works with EC2.
+	 * 
+	 * TODO: Test this method.
+	 * 
+	 * @param name is the nam eof the security group to create
+	 * @param description is a human-readable description of the group
+	 * 
+	 * @return Object is the parsed object as defined and handled by EC2Handler
+	 */
+	public Object exCreateSecurityGroup(String name, String description) {
+		Map<String, String> params = new HashMap<String, String>();
+		params.put("Action", "CreateSecurityGroup");
+		params.put("GroupName", name);
+		params.put("GroupDescription", description);
+		IResponse response = connection.request("GET", "/", null, params, null);
+		EC2Handler handler = new EC2Handler(response);
+		return handler.getParsedObject();
+	}
+	
+	/*
+	 * Edit a Security Group to allow all traffic.
+	 * 
+	 * Note: This is a non-standard extension API and only works with EC2.
+	 * 
+	 * TODO: Test this method.
+	 * 
+	 * @param name is the name of the security group to edit
+	 * 
+	 * @return List<Object> is a list of parsed objects as defined & handled by EC2Handler
+	 */
+	public List<Object> exAuthorizeSecurityGroupPermissive(String name) {
+		List<Object> results = new ArrayList<Object>();
+		
+		// Request 1
+		Map<String, String> params = new HashMap<String, String>();
+		params.put("Action", "AuthorizeSecurityGroupIngress");
+		params.put("GroupName", name);
+		params.put("IpProtocol", "tcp");
+		params.put("FromPort", "0");
+		params.put("ToPort", "65535");
+		params.put("CidrIp", "0.0.0.0/0");
+		try {
+			IResponse response = connection.request("GET", "/", null, params, null);
+			EC2Handler handler = new EC2Handler(response);
+			results.add(handler.getParsedObject());
+		} catch(Exception e) {
+			if (!e.getMessage().contains("InvalidPermission.Duplicate")) {
+				throw new RuntimeException(e);
+			}
+		}
+		
+		// Request 2
+		params.put("IpProtocol", "udo");
+		try {
+			IResponse response = connection.request("GET", "/", null, params, null);
+			EC2Handler handler = new EC2Handler(response);
+			results.add(handler.getParsedObject());
+		} catch(Exception e) {
+			if (!e.getMessage().contains("InvalidPermission.Duplicate")) {
+				throw new RuntimeException(e);
+			}
+		}
+		
+		// Request 3
+		params.put("IpProtocol", "icmp");
+		params.put("FromPort", "-1");
+		params.put("ToPort", "-1");
+		try {
+			IResponse response = connection.request("GET", "/", null, params, null);
+			EC2Handler handler = new EC2Handler(response);
+			results.add(handler.getParsedObject());
+		} catch(Exception e) {
+			if (!e.getMessage().contains("InvalidPermission.Duplicate")) {
+				throw new RuntimeException(e);
+			}
+		}
+		return results;
+	}
+	
+	// ----------------------------- HIDDEN HELPERS ---------------------------
+	private List<INode> parseNodesByGroup(Element elem) {
+		try {
+			List<INode> nodes = new ArrayList<INode>();
+			NodeList reservationList = (NodeList)xpath.evaluate("reservationSet/item", elem, XPathConstants.NODESET);
+			for (int rIdx = 0; rIdx < reservationList.getLength(); rIdx++) {
+				Element rs = (Element)reservationList.item(rIdx);
+				List<String> groups = new ArrayList<String>();
+				NodeList groupList = (NodeList)xpath.evaluate("groupSet/item", rs, XPathConstants.NODESET);
+				for (int gsIdx = 0; gsIdx < groupList.getLength(); gsIdx++) {
+					groups.add(xpath.evaluate("groupId", groupList.item(gsIdx)));
+				}
+				nodes.addAll(parseNodes(rs, "instancesSet/item", groups));
+			}
+			return nodes;
+		} catch (XPathExpressionException e) {
+			e.printStackTrace();
+		}
+		return null;	// Error
+	}
+	
+	private List<INode> parseNodes(Element elem, String path, List<String> groups) {
+		try {
+			List<INode> nodes = new ArrayList<INode>();
+			NodeList instanceSet = (NodeList)xpath.evaluate(path, elem, XPathConstants.NODESET);
+			for (int i = 0; i < instanceSet.getLength(); i++) {
+				nodes.add(parseNode((Element)instanceSet.item(i), groups));
+			}
+			return nodes;
+		} catch (XPathExpressionException e) {
+			e.printStackTrace();
+		}
+		return null;	// Error
+	}
+	
+	private INode parseNode(Element elem, List<String> groups) throws XPathExpressionException {
+		// Node parameters
+		String id = xpath.evaluate("instanceId", elem);
+		String name = xpath.evaluate("instanceId", elem);
+		NodeState state = NODE_STATE_MAP.get(xpath.evaluate("instanceState/name", elem));
+		String publicIp = xpath.evaluate("dnsName", elem);
+		String privateIp = xpath.evaluate("privateDnsName", elem);
+		
+		// Extra parameter
+		Map<String, Object> extra = new HashMap<String, Object>();
+		extra.put("dnsName", xpath.evaluate("dnsName", elem));
+		extra.put("instanceId", xpath.evaluate("instanceId", elem));
+		extra.put("imageId", xpath.evaluate("imageId", elem));
+		extra.put("privateDns", xpath.evaluate("privateDns", elem));
+		extra.put("status", xpath.evaluate("instanceState/name", elem));
+		extra.put("keyName", xpath.evaluate("keyName", elem));
+		extra.put("launchIndex", xpath.evaluate("amiLaunchIndex", elem));
+		NodeList productSet = (NodeList)xpath.evaluate("productCodesSet/item", elem, XPathConstants.NODESET);
+		List<String> productCodes = new ArrayList<String>();
+		for (int i = 0; i < productSet.getLength(); i++) {
+			productCodes.add(xpath.evaluate("productCode", productSet.item(i)));
+		}
+		extra.put("productCode", productCodes);
+		extra.put("instanceType", xpath.evaluate("instanceType", elem));
+		extra.put("launchdatetime", xpath.evaluate("launchTime", elem));
+		extra.put("availability", xpath.evaluate("placement/availabilityZone", elem));
+		extra.put("kernelId", xpath.evaluate("kernelId", elem));
+		extra.put("ramdiskId", xpath.evaluate("ramdiskId", elem));
+		if (groups != null) extra.put("groups", groups);
+		
+		// Construct final node and return!
+		return new Node(id, name, state, publicIp, privateIp, extra, this);
+	}
+	
+	private List<NodeImage> parseImages(Document doc) {
+		List<NodeImage> images = new ArrayList<NodeImage>();
+		try {
+			NodeList imageSet = (NodeList)xpath.evaluate("imagesSet/item", doc.getDocumentElement(), XPathConstants.NODESET);
+			for (int i = 0; i < imageSet.getLength(); i++) {
+				images.add(parseImage((Element)imageSet.item(i)));
+			}
+			return images;
+		} catch (XPathExpressionException e) {
+			e.printStackTrace();
+		}
+		return null;	// Error
+	}
+	
+	private NodeImage parseImage(Element elem) throws XPathExpressionException {
+		return new NodeImage(xpath.evaluate("imageId", elem),
+				xpath.evaluate("imageLocation", elem),
+				null,
+				this);
+	}
+	
+	/*
+	 * Converts a key and array of values into a map for AWS query parameters.
+	 * 
+	 * @param key is the key for the array of values
+	 * @param values are the values to compose the query
+	 * 
+	 * @return Map<String, String> are parameters for the AWS query
+	 */
+	private Map<String, String> pathList(String key, String[] values) {
+		Map<String, String> params = new HashMap<String, String>();
+		for (int i = 0; i < values.length; i++) {
+			params.put(key + '.' + (i + 1), values[i]);
+		}
+		return params;
+	}
+	
+	private boolean parseRebootBoolean(Document doc) {
+		try {
+			return ((String)xpath.evaluate("return", doc.getDocumentElement())).equals("true");
+		} catch (XPathExpressionException e) {
+			e.printStackTrace();
+		}
+		return false;
+	}
+	
+	private boolean parseTerminateBoolean(Document doc) {
+		try {
+			String currentState = (String)xpath.evaluate("instancesSet/item/currentState/name", doc.getDocumentElement());
+			return currentState.equals("shutting-down") || currentState.equals("terminated");
+		} catch (XPathExpressionException e) {
+			e.printStackTrace();
+		}
+		return false;
+	}
+	
+	/*
+	 * Base Amazon EC2 instance types.  Subclasses set the prices.
+	 */
+	protected static Map<String, NodeSize> initNodeSizes() {
+		Map<String, NodeSize> sizes = new HashMap<String, NodeSize>();
+		sizes.put("m1.small", new NodeSize("m1.small", "Small Instance", 1740, 160, -1, -1f, null));
+		sizes.put("m1.large", new NodeSize("m1.large", "Large Instance", 7680, 850, -1, -1f, null));
+		sizes.put("m1.xlarge", new NodeSize("m1.xlarge", "Extra Large Instance", 15360, 1690, -1, -1f, null));
+		sizes.put("c1.medium", new NodeSize("c1.medium", "High-CPU Medium Instance", 1740, 350, -1, -1f, null));
+		sizes.put("c1.xlarge", new NodeSize("c1.xlarge", "High-CPU Extra Large Instance", 7680, 1960, -1, -1f, null));
+		sizes.put("m2.xlarge", new NodeSize("m2.xlarge", "High-Memory Extra Large Instance", 17510, 420, -1, -1f, null));
+		sizes.put("m2.2xlarge", new NodeSize("m2.2xlarge", "High-Memory Double Extra Large Instance", 35021, 850, -1, -1f, null));
+		sizes.put("m2.4xlarge", new NodeSize("m2.4xlarge", "High-Memory Quadruple Extra Large Instance", 70042, 1690, -1, -1f, null));
+		return sizes;
+	}
+	
+	/*
+	 * Retrieves the price for a NodeSize.  Subclass implements its own prices.
+	 * 
+	 * @param sizeId identifies the node configuration
+	 * 
+	 * @return float is the price of the node configuration
+	 */
+	protected abstract float getPrice(String sizeId);
+}

Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2EUWestDriver.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2EUWestDriver.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2EUWestDriver.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2EUWestDriver.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,46 @@
+package libcloud.providers.amazon;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import libcloud.data.NodeLocation;
+
+public class EC2EUWestDriver extends EC2Driver {
+	
+	private static final String EC2_EU_WEST_HOST = "ec2.eu-west-1.amazonaws.com";
+	
+	private static final Map<String, Float> EC2_EU_WEST_PRICES = initNodePrices();
+		
+	public EC2EUWestDriver(String accessId, String accessKey) {
+		super(accessId, accessKey, EC2_EU_WEST_HOST);
+	}
+
+	public List<NodeLocation> listLocations() {
+		List<NodeLocation> locations = new ArrayList<NodeLocation>();
+		locations.add(new NodeLocation("0", "Amazon Europe Ireland", "IE", this));
+		return locations;
+	}
+	
+	public String getName() {
+		return "Amazon EC2 (eu-west-1)";
+	}
+	
+	protected float getPrice(String sizeId) {
+		return EC2_EU_WEST_PRICES.get(sizeId);
+	}
+	
+	private static Map<String, Float> initNodePrices() {
+		Map<String, Float> prices = new HashMap<String, Float>();
+		prices.put("m1.small", .095f);
+		prices.put("m1.large", .38f);
+		prices.put("m1.xlarge", .76f);
+		prices.put("c1.medium", .19f);
+		prices.put("c1.xlarge", .76f);
+		prices.put("m2.xlarge", .57f);
+		prices.put("m2.2xlarge", 1.14f);
+		prices.put("m2.4xlarge", 2.28f);
+		return prices;
+	}
+}

Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Handler.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Handler.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Handler.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Handler.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,83 @@
+package libcloud.providers.amazon;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import libcloud.exceptions.InvalidCredsException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import base.connection.ResponseHandler;
+import base.interfaces.IResponse;
+
+public class EC2Handler extends ResponseHandler {
+
+	public EC2Handler(IResponse response) {
+		super(response);
+	}
+	
+	protected void parseBody() {
+		object = null;
+		try {
+			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+			DocumentBuilder db = dbf.newDocumentBuilder();
+			object = db.parse(new InputSource(new StringReader(response.getBody())));
+		} catch (ParserConfigurationException e) {
+			e.printStackTrace();
+		} catch (SAXException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+	
+	protected String parseError() {
+		try {
+			// Parse errors
+			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+			DocumentBuilder db = dbf.newDocumentBuilder();
+			Document doc = db.parse(new InputSource(new StringReader(response.getBody())));
+			XPath xpath = XPathFactory.newInstance().newXPath();
+			NodeList errors = (NodeList)xpath.evaluate("Errors/Error", doc.getDocumentElement(), XPathConstants.NODESET);
+			
+			// Process errors
+			StringBuffer sb = new StringBuffer();
+			for (int i = 0; i < errors.getLength(); i++) {
+				String error = (String)xpath.evaluate("Code", errors.item(i));
+				String message = (String)xpath.evaluate("Message", errors.item(i));
+				if (error.equals("InvalidClientTokenId")) {
+					throw new InvalidCredsException(response.getStatus() + " " + error + ": " + message);
+				} else if (error.equals("SignatureDoesNotMatch")) {
+					throw new InvalidCredsException(response.getStatus() + " " + error + ": " + message);
+				} else if (error.equals("AuthFailure")) {
+					throw new InvalidCredsException(response.getStatus() + " " + error + ": " + message);
+				} else if (error.equals("OptInRequired")) {
+					throw new InvalidCredsException(response.getStatus() + " " + error + ": " + message);
+				} else {
+					sb.append(response.getStatus() + " " + error + ": " + message + '\n');
+				}
+			}
+			return sb.toString().trim();
+		} catch (ParserConfigurationException e) {
+			e.printStackTrace();
+		} catch (SAXException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		} catch (XPathExpressionException e) {
+			e.printStackTrace();
+		}
+		return super.parseError();
+	}
+}

Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2USEastDriver.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2USEastDriver.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2USEastDriver.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2USEastDriver.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,46 @@
+package libcloud.providers.amazon;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import libcloud.data.NodeLocation;
+
+public class EC2USEastDriver extends EC2Driver {
+	
+	private static final String EC2_US_EAST_HOST = "ec2.us-east-1.amazonaws.com";
+	
+	private static final Map<String, Float> EC2_US_EAST_PRICES = initNodePrices();
+		
+	public EC2USEastDriver(String accessId, String accessKey) {
+		super(accessId, accessKey, EC2_US_EAST_HOST);
+	}
+
+	public List<NodeLocation> listLocations() {
+		List<NodeLocation> locations = new ArrayList<NodeLocation>();
+		locations.add(new NodeLocation("0", "Amazon US N. Virginia", "US", this));
+		return locations;
+	}
+	
+	public String getName() {
+		return "Amazon EC2 (us-east-1)";
+	}
+	
+	protected float getPrice(String sizeId) {
+		return EC2_US_EAST_PRICES.get(sizeId);
+	}
+	
+	private static Map<String, Float> initNodePrices() {
+		Map<String, Float> prices = new HashMap<String, Float>();
+		prices.put("m1.small", .085f);
+		prices.put("m1.large", .34f);
+		prices.put("m1.xlarge", .68f);
+		prices.put("c1.medium", .17f);
+		prices.put("c1.xlarge", .68f);
+		prices.put("m2.xlarge", .50f);
+		prices.put("m2.2xlarge", 1.00f);
+		prices.put("m2.4xlarge", 2.00f);
+		return prices;
+	}
+}

Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2USWestDriver.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2USWestDriver.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2USWestDriver.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2USWestDriver.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,46 @@
+package libcloud.providers.amazon;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import libcloud.data.NodeLocation;
+
+public class EC2USWestDriver extends EC2Driver {
+	
+	private static final String EC2_US_WEST_HOST = "ec2.us-west-1.amazonaws.com";
+	
+	private static final Map<String, Float> EC2_US_WEST_PRICES = initNodePrices();
+		
+	public EC2USWestDriver(String accessId, String accessKey) {
+		super(accessId, accessKey, EC2_US_WEST_HOST);
+	}
+
+	public List<NodeLocation> listLocations() {
+		List<NodeLocation> locations = new ArrayList<NodeLocation>();
+		locations.add(new NodeLocation("0", "Amazon US N. California", "US", this));
+		return locations;
+	}
+	
+	public String getName() {
+		return "Amazon EC2 (us-west-1)";
+	}
+	
+	protected float getPrice(String sizeId) {
+		return EC2_US_WEST_PRICES.get(sizeId);
+	}
+	
+	private static Map<String, Float> initNodePrices() {
+		Map<String, Float> prices = new HashMap<String, Float>();
+		prices.put("m1.small", .095f);
+		prices.put("m1.large", .38f);
+		prices.put("m1.xlarge", .76f);
+		prices.put("c1.medium", .19f);
+		prices.put("c1.xlarge", .76f);
+		prices.put("m2.xlarge", .57f);
+		prices.put("m2.2xlarge", 1.14f);
+		prices.put("m2.4xlarge", 2.28f);
+		return prices;
+	}
+}

Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMConnection.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMConnection.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMConnection.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMConnection.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,32 @@
+package libcloud.providers.ibm;
+
+import java.util.Map;
+
+import libcloud.NodeDriver;
+
+import org.apache.commons.codec.binary.Base64;
+
+import base.connection.ConnectionUserAndKey;
+
+public class IBMConnection extends ConnectionUserAndKey {
+	
+	private static final String DEFAULT_HOST = "www-147.ibm.com";
+	private static final boolean DEFAULT_SECURE = true;
+	
+	public IBMConnection(String userId, String key, NodeDriver driver) {
+		super(userId, key, DEFAULT_SECURE, DEFAULT_HOST, driver);
+	}
+
+	public IBMConnection(String userId, String password, boolean secure,
+			String host, int port, NodeDriver driver) {
+		super(userId, password, secure, host, port, driver);
+	}
+	
+	protected Map<String, String> addDefaultHeaders(Map<String, String> headers) {
+		headers.put("Accept", "text/xml");
+		String authorization = "Basic " + new String(Base64.encodeBase64((accessId + ":" + accessKey).getBytes()));
+		headers.put("Authorization", authorization);
+		headers.put("Content-Type", "text/xml");
+		return headers;
+	}
+}

Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMConnection.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMDriver.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMDriver.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMDriver.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMDriver.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,229 @@
+package libcloud.providers.ibm;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import libcloud.NodeDriver;
+import libcloud.data.Node;
+import libcloud.data.NodeAuth;
+import libcloud.data.NodeImage;
+import libcloud.data.NodeLocation;
+import libcloud.data.NodeSize;
+import libcloud.data.NodeState;
+import libcloud.interfaces.INode;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import base.connection.ConnectionKey;
+import base.interfaces.IResponse;
+
+/*
+ * TODO: comment all classes
+ * TODO: overload constructor with userId, key, host, and port
+ * TODO: listImages(NodeLocation)
+ * TODO: listSizes(NodeLocation)
+ * TODO: update to use XPath -- See Amazon EC2 Driver
+ */
+public class IBMDriver extends NodeDriver {
+
+	private static final String REST_BASE = "/computecloud/enterprise/api/rest/20100331";
+
+	private static final Map<Integer, NodeState> NODE_STATE_MAP = new HashMap<Integer, NodeState>();
+
+	public IBMDriver(String userId, String key) {
+		connection = new IBMConnection(userId, key, this);
+
+		// Map IBM instance states to libcloud
+		NODE_STATE_MAP.put(0, NodeState.PENDING);
+		NODE_STATE_MAP.put(1, NodeState.PENDING);
+		NODE_STATE_MAP.put(2, NodeState.TERMINATED);
+		NODE_STATE_MAP.put(3, NodeState.TERMINATED);
+		NODE_STATE_MAP.put(4, NodeState.TERMINATED);
+		NODE_STATE_MAP.put(5, NodeState.RUNNING);
+		NODE_STATE_MAP.put(6, NodeState.UNKNOWN);
+		NODE_STATE_MAP.put(7, NodeState.PENDING);
+		NODE_STATE_MAP.put(8, NodeState.REBOOTING);
+		NODE_STATE_MAP.put(9, NodeState.PENDING);
+		NODE_STATE_MAP.put(10, NodeState.PENDING);
+		NODE_STATE_MAP.put(11, NodeState.TERMINATED);
+		NODE_STATE_MAP.put(12, NodeState.PENDING);	// Deprovision pending
+		NODE_STATE_MAP.put(13, NodeState.PENDING);	// Restart pending
+	}
+
+	public String getName() {
+		return "IBM Smart Business Development and Test Cloud";
+	}
+
+	public INode createNode(String name, NodeSize size, NodeImage image,
+			NodeLocation location, NodeAuth auth, Map<String, Object> extra) {
+		// Compose headers for message body
+		Map<String, String> data = new HashMap<String, String>();
+		data.put("name", name);
+		data.put("imageID", image.id);
+		data.put("instanceType", size.id);
+		if (location != null) {
+			data.put("location", location.id);
+		}
+		if (auth != null) {
+			data.put("publicKey", auth.secret);
+		}
+		if (extra != null) {
+			for (String key : extra.keySet()) {
+				data.put(key, (String)extra.get(key));
+			}
+		}
+		
+		String encoded = ConnectionKey.urlEncodeMap(data);
+		Map<String, String> headers = new HashMap<String, String>();
+		headers.put("Content-Type", "application/x-www-form-urlencoded");
+		IResponse response = connection.request("POST", REST_BASE + "/instances", headers, null, encoded);
+		IBMHandler handler = new IBMHandler(response);
+		return parseNodes((Document)handler.getParsedObject()).get(0);
+	}
+
+	public boolean rebootNode(INode node) {
+		Map<String, String> headers = new HashMap<String, String>();
+		headers.put("Content-Type", "application/x-www-form-urlencoded");
+		Map<String, String> data = new HashMap<String, String>();
+		data.put("state", "restart");
+		IResponse response = connection.request("PUT", REST_BASE + "/instances/" + node.getId(), headers, null, ConnectionKey.urlEncodeMap(data));
+		new IBMHandler(response);
+		return response.getStatus() == 200;
+	}
+
+	public boolean destroyNode(INode node) {
+		IResponse response = connection.request("DELETE", REST_BASE + "/instances/" + node.getId(), null, null, "");
+		new IBMHandler(response);
+		return response.getStatus() == 200;
+	}
+
+	public List<NodeImage> listImages() {
+		IResponse response = connection.request("GET", REST_BASE + "/offerings/image", null, null, "");
+		IBMHandler handler = new IBMHandler(response);
+		return parseImages((Document)handler.getParsedObject());
+	}
+
+	public List<NodeLocation> listLocations() {
+		IResponse response = connection.request("GET", REST_BASE + "/locations", null, null, "");
+		IBMHandler handler = new IBMHandler(response);
+		return parseLocations((Document)handler.getParsedObject());
+	}
+
+	public List<INode> listNodes() {
+		IResponse response = connection.request("GET", REST_BASE + "/instances", null, null, "");
+		IBMHandler handler = new IBMHandler(response);
+		return parseNodes((Document)handler.getParsedObject());
+	}
+
+	public List<NodeSize> listSizes() {
+		List<NodeSize> sizes = new ArrayList<NodeSize>();
+		sizes.add(new NodeSize("BRZ32.1/2048/175", "Bronze 32 bit", -1, -1, -1, -1, this));
+		sizes.add(new NodeSize("BRZ64.2/4096/850", "Bronze 64 bit", -1, -1, -1, -1, this));
+		sizes.add(new NodeSize("SLV32.2/4096/350", "Silver 32 bit", -1, -1, -1, -1, this));
+		sizes.add(new NodeSize("SLV64.4/8192/1024", "Silver 64 bit", -1, -1, -1, -1, this));
+		sizes.add(new NodeSize("GLD32.4/4096/350", "Bronze 32 bit", -1, -1, -1, -1, this));
+		sizes.add(new NodeSize("GLD64.8/16384/1024", "Gold 64 bit", -1, -1, -1, -1, this));
+		sizes.add(new NodeSize("PLT64.16/16384/2045", "Platinum 64 bit", -1, -1, -1, -1, this));
+		return sizes;
+	}
+
+	// ----------------------------- PRIVATE HELPERS ---------------------------
+
+	private List<NodeImage> parseImages(Document doc) {
+		List<NodeImage> images = new ArrayList<NodeImage>();
+		List<Element> elems = getFirstElementsByTagName(doc
+				.getDocumentElement(), "Image");
+		for (Element elem : elems) {
+			images.add(parseImage(elem));
+		}
+		return images;
+	}
+
+	private NodeImage parseImage(Element elem) {
+		return new NodeImage(getTextValue(elem, "ID"),
+				getTextValue(elem, "Name"),
+				null, // TODO: include parametersUrl in extra
+				this);
+	}
+
+	private List<INode> parseNodes(Document doc) {
+		List<INode> nodes = new ArrayList<INode>();
+		List<Element> elems = getFirstElementsByTagName(doc.getDocumentElement(), "Instance");
+		for (Element elem : elems) {
+			nodes.add(parseNode(elem));
+		}
+		return nodes;
+	}
+
+	private INode parseNode(Element elem) {
+		return new Node(getTextValue(elem, "ID"),
+				getTextValue(elem, "Name"),
+				NODE_STATE_MAP.get(new Integer(getTextValue(elem, "Status"))),
+				getTextValue(elem, "IP"),
+				null,
+				null,
+				this);
+	}
+
+	private List<NodeLocation> parseLocations(Document doc) {
+		List<NodeLocation> locations = new ArrayList<NodeLocation>();
+		List<Element> elems = getFirstElementsByTagName(doc
+				.getDocumentElement(), "Location");
+		for (Element elem : elems) {
+			locations.add(parseLocation(elem));
+		}
+		return locations;
+	}
+
+	private NodeLocation parseLocation(Element elem) {
+		return new NodeLocation(getTextValue(elem, "ID"), getTextValue(elem, "Name"), "US", this);
+	}
+	
+	/*
+	 * Utility function to extract the text value of the given element.
+	 * 
+	 * @param elem is the element to find the tag in
+	 * @param tagName is the name of the tag to find the value for
+	 * 
+	 * @return String is the text value of the given tag
+	 */
+	public static String getTextValue(Element elem, String tagName) {
+		NodeList nl = elem.getElementsByTagName(tagName);
+		if (nl.getLength() > 0) {
+			if (nl.item(0).getFirstChild() == null) {
+				return "";
+			} else {
+				return nl.item(0).getFirstChild().getNodeValue();
+			}
+		} else {
+			return null;
+		}
+	}
+
+	/*
+	 * Utility function that returns a list of immediate children to the given
+	 * Element and that matches the given tagName.
+	 * 
+	 * TODO: Use XPath instead (see Amazon EC2 driver)
+	 * 
+	 * @param elem is the parent of the elements to search
+	 * @param tagName identifies the elements to find
+	 * 
+	 * @return List<Element> is a list of immediate children matching tagName
+	 */
+	public static List<Element> getFirstElementsByTagName(Element elem, String tagName) {
+		List<Element> elements = new ArrayList<Element>();
+		NodeList children = elem.getChildNodes();
+		for (int i = 0; i < children.getLength(); i++) {
+			Element child = (Element) children.item(i);
+			if (child.getTagName().equals(tagName)) {
+				elements.add(child);
+			}
+		}
+		return elements;
+	}
+}

Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMDriver.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMHandler.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMHandler.java?rev=997113&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMHandler.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMHandler.java Tue Sep 14 21:57:01 2010
@@ -0,0 +1,51 @@
+package libcloud.providers.ibm;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import libcloud.exceptions.InvalidCredsException;
+
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import base.connection.ResponseHandler;
+import base.interfaces.IResponse;
+
+public class IBMHandler extends ResponseHandler {
+
+	public IBMHandler(IResponse response) {
+		super(response);
+	}
+
+	protected void parseBody() {
+		object = null;
+		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+		try {
+			DocumentBuilder db = dbf.newDocumentBuilder();
+			object = db.parse(new InputSource(new StringReader(response.getBody())));
+		} catch (ParserConfigurationException e) {
+			e.printStackTrace();
+		} catch (SAXException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+
+	protected String parseError() {
+		if (response.getStatus() == 401) {
+			if (response.getBody().equals("")) {
+				throw new InvalidCredsException(response.getStatus() + ": "
+						+ response.getPhrase());
+			} else {
+				throw new InvalidCredsException(response.getBody());
+			}
+		} else {
+			return (String)response.getBody();
+		}
+	}
+}

Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMHandler.java
------------------------------------------------------------------------------
    svn:executable = *