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/22 18:26:58 UTC
svn commit: r1000070 - in
/incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage:
interfaces/IStorageAdapter.java providers/amazon/S3Adapter.java
providers/nirvanix/NirvanixAdapter.java
Author: woodser
Date: Wed Sep 22 16:26:57 2010
New Revision: 1000070
URL: http://svn.apache.org/viewvc?rev=1000070&view=rev
Log:
Added metadata management support to Nirvanix & Amazon S3 adapters.
- 10/10 calls implemented for Amazon S3
- 10/10 calls implemented for Nirvanix
- Modification to IStorageAdapter interface to support metadata calls
Modified:
incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/interfaces/IStorageAdapter.java
incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/amazon/S3Adapter.java
incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/nirvanix/NirvanixAdapter.java
Modified: incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/interfaces/IStorageAdapter.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/interfaces/IStorageAdapter.java?rev=1000070&r1=1000069&r2=1000070&view=diff
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/interfaces/IStorageAdapter.java (original)
+++ incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/interfaces/IStorageAdapter.java Wed Sep 22 16:26:57 2010
@@ -16,7 +16,7 @@ public interface IStorageAdapter {
public IItem fetchItem(String path, Map<Object, Object> options);
- public boolean storeItem(String destinationPath, IItem item, Map<Object, Object> options);
+ public boolean storeItem(String destinationPath, IItem item, Map<String, String> metadata, Map<Object, Object> options);
public void deleteItem(String path, Map<Object, Object> options);
Modified: incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/amazon/S3Adapter.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/amazon/S3Adapter.java?rev=1000070&r1=1000069&r2=1000070&view=diff
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/amazon/S3Adapter.java (original)
+++ incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/amazon/S3Adapter.java Wed Sep 22 16:26:57 2010
@@ -26,9 +26,7 @@ import base.interfaces.IResponse;
/*
* Adapter for interacting with Amazon S3.
*
- * TODO: different locations
- * TODO: comment required option parameters
- * TODO: general comments
+ * TODO: support different geographic locations
*/
public class S3Adapter extends StorageAdapter {
@@ -54,6 +52,9 @@ public class S3Adapter extends StorageAd
connection = new S3Connection(accessId, accessKey, host, this);
}
+ /*
+ * Required options: Type.SRC_BUCKET
+ */
public IItem fetchItem(String path, Map<Object, Object> options) {
String bucket = (String)options.get(Type.SRC_BUCKET);
connection.connect(bucket + '.' + HOST);
@@ -62,14 +63,20 @@ public class S3Adapter extends StorageAd
return (IItem)rh.getParsedObject();
}
- public boolean storeItem(String destinationPath, IItem item, Map<Object, Object> options) {
+ /*
+ * Required options: Type.SRC_BUCKET
+ */
+ public boolean storeItem(String destinationPath, IItem item, Map<String, String> metadata, Map<Object, Object> options) {
String bucket = (String)options.get(Type.SRC_BUCKET);
connection.connect(bucket + '.' + HOST);
- IResponse response = connection.request("PUT", destinationPath, null, null, item);
+ IResponse response = connection.request("PUT", destinationPath, metadata, null, item);
new S3Handler(response);
return response.getStatus() == 200;
}
+ /*
+ * Required options: Type.SRC_BUCKET
+ */
public void deleteItem(String path, Map<Object, Object> options) {
String bucket = (String)options.get(Type.SRC_BUCKET);
connection.connect(bucket + '.' + HOST);
@@ -77,6 +84,9 @@ public class S3Adapter extends StorageAd
new S3Handler(response);
}
+ /*
+ * Required options: Type.SRC_BUCKET, Type.DEST_BUCKET
+ */
public void copyItem(String sourcePath, String destinationPath, Map<Object, Object> options) {
String srcBucket = (String)options.get(Type.SRC_BUCKET);
String destBucket = (String)options.get(Type.DEST_BUCKET);
@@ -87,6 +97,9 @@ public class S3Adapter extends StorageAd
new S3Handler(response);
}
+ /*
+ * Required options: Type.SRC_BUCKET, Type.DEST_BUCKET
+ */
public void moveItem(String sourcePath, String destinationPath, Map<Object, Object> options) {
// Copy the item
String srcBucket = (String)options.get(Type.SRC_BUCKET);
@@ -103,12 +116,18 @@ public class S3Adapter extends StorageAd
new S3Handler(response);
}
+ /*
+ * Required options: Type.SRC_BUCKET
+ */
public void renameItem(String path, String name, Map<Object, Object> options) {
String destPath = path.substring(0, path.lastIndexOf('/') + 1) + name;
options.put(Type.DEST_BUCKET, options.get(Type.SRC_BUCKET));
moveItem(path, destPath, options);
}
+ /*
+ * Required options: Type.SRC_BUCKET
+ */
public List<String> listItems(String path, Map<Object, Object> options) {
String bucket = (String)options.get(Type.SRC_BUCKET);
connection.connect(bucket + '.' + HOST);
@@ -130,22 +149,37 @@ public class S3Adapter extends StorageAd
return null; // Error
}
- @Override
+ /*
+ * Required options: Type.SRC_BUCKET
+ */
public Map<String, String> fetchMetadata(String path, Map<Object, Object> options) {
- // TODO Auto-generated method stub
- return null;
+ String bucket = (String)options.get(Type.SRC_BUCKET);
+ connection.connect(bucket + '.' + HOST);
+ IResponse response = connection.request("GET", path, null, null, null);
+ new S3Handler(response);
+ return response.getHeaders();
}
- @Override
+ /*
+ * The key/value metadata is forwarded directly to the server without
+ * interpretation.
+ *
+ * Required options: Type.SRC_BUCKET
+ */
public void storeMetadata(String destinationPath, Map<String, String> metadata, Map<Object, Object> options) {
- // TODO Auto-generated method stub
-
+ String bucket = (String)options.get(Type.SRC_BUCKET);
+ connection.connect(bucket + '.' + HOST);
+ IResponse response = connection.request("PUT", destinationPath, metadata, null, null);
+ new S3Handler(response);
}
- @Override
+ /*
+ * Amazon S3 does not currently support deleting metadata.
+ *
+ * Workaround: fetchItem, deleteItem, then storeItem with updated metadata
+ */
public void deleteMetadata(String path, Map<Object, Object> options) {
- // TODO Auto-generated method stub
-
+ throw new RuntimeException("Deleting metadata is not supported");
}
private List<String> parseItems(Element elem) {
Modified: incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/nirvanix/NirvanixAdapter.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/nirvanix/NirvanixAdapter.java?rev=1000070&r1=1000069&r2=1000070&view=diff
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/nirvanix/NirvanixAdapter.java (original)
+++ incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/nirvanix/NirvanixAdapter.java Wed Sep 22 16:26:57 2010
@@ -94,8 +94,9 @@ public class NirvanixAdapter extends Dri
/*
* TODO: This was hacked together because of lacking multipart-form posts in ConnectionKey.
+ * TODO: metadata
*/
- public boolean storeItem(String destinationPath, IItem item, Map<Object, Object> options) {
+ public boolean storeItem(String destinationPath, IItem item, Map<String, String> metadata, Map<Object, Object> options) {
// First get the StorageNode
Map<String, String> nodeParams = new HashMap<String, String>();
nodeParams.put("sessionToken", sessionToken);
@@ -219,22 +220,47 @@ public class NirvanixAdapter extends Dri
return parseItems((Document)rh.getParsedObject());
}
- @Override
public Map<String, String> fetchMetadata(String path, Map<Object, Object> options) {
- // TODO Auto-generated method stub
- return null;
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("sessionToken", sessionToken);
+ params.put("path", path);
+ IResponse response = connection.request("GET", "/ws/Metadata/GetMetadata.ashx", null, params, null);
+ NirvanixHandler handler = new NirvanixHandler(response);
+ return parseMetadata((Document)handler.getParsedObject());
}
- @Override
+ /*
+ * NOTE: Because Nirvanix specifies multiple metadata key/value pairs with
+ * the same key, and a Map is used to store the key/value pairs, only one
+ * metadata item may be stored at a time.
+ *
+ * TODO: Possibly use List<KeyValuePair> for headers/params? Map does not
+ * support multi-mapping.
+ */
public void storeMetadata(String destinationPath, Map<String, String> metadata, Map<Object, Object> options) {
- // TODO Auto-generated method stub
-
+ if (metadata.keySet().size() != 1) {
+ throw new RuntimeException("Support limitation: exactly one metadata key/value pair must be set");
+ }
+
+ String metadataParam = "";
+ for (String key : metadata.keySet()) {
+ metadataParam += key + ":" + metadata.get(key);
+ }
+
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("sessionToken", sessionToken);
+ params.put("path", destinationPath);
+ params.put("metadata", metadataParam);
+ IResponse response = connection.request("GET", "/ws/Metadata/SetMetadata.ashx", null, params, null);
+ new NirvanixHandler(response);
}
- @Override
public void deleteMetadata(String path, Map<Object, Object> options) {
- // TODO Auto-generated method stub
-
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("sessionToken", sessionToken);
+ params.put("path", path);
+ IResponse response = connection.request("GET", "/ws/Metadata/DeleteAllMetadata.ashx", null, params, null);
+ new NirvanixHandler(response);
}
private List<String> parseDownloadNodes(Document doc) {
@@ -293,6 +319,22 @@ public class NirvanixAdapter extends Dri
return null; // Error
}
+ private Map<String, String> parseMetadata(Document doc) {
+ try {
+ Map<String, String> metadata = new HashMap<String, String>();
+ XPath xpath = XPathFactory.newInstance().newXPath();
+ NodeList types = (NodeList)xpath.evaluate("/Response/Metadata/Type", doc.getDocumentElement(), XPathConstants.NODESET);
+ NodeList values = (NodeList)xpath.evaluate("/Response/Metadata/Value", doc.getDocumentElement(), XPathConstants.NODESET);
+ for (int i = 0; i < types.getLength(); i++) {
+ metadata.put(types.item(i).getTextContent(), values.item(i).getTextContent());
+ }
+ return metadata;
+ } catch (XPathExpressionException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
/*
* Simple extension of InputStreamBody to support length.
*