createContainer, deleteContainer, updates to container to parse metadata and accompany testcases.

Added handling of null ObjectName.
This commit is contained in:
Kenneth Nagin 2012-05-20 14:56:01 +03:00 committed by Adrian Cole
parent 227dbf777a
commit 3d1a2dd7fa
6 changed files with 365 additions and 200 deletions

View File

@ -29,7 +29,7 @@ import com.google.common.base.Objects.ToStringHelper;
/** /**
* The base type for all objects in the CDMI model. * The base type for all objects in the CDMI model.
* *
* @author Adrian Cole * @author Kenneth Nagin
*/ */
public class CDMIObject { public class CDMIObject {
@ -83,7 +83,8 @@ public class CDMIObject {
} }
protected B fromCDMIObject(CDMIObject in) { protected B fromCDMIObject(CDMIObject in) {
return objectID(in.getObjectID()).objectType(in.getObjectType()).objectName(in.getObjectName()); return objectID(in.getObjectID()).objectType(in.getObjectType())
.objectName(in.getObjectName());
} }
} }
@ -99,13 +100,18 @@ public class CDMIObject {
/** /**
* Object ID of the object <br/> * Object ID of the object <br/>
* Every object stored within a CDMI-compliant system shall have a globally unique object * Every object stored within a CDMI-compliant system shall have a globally
* identifier (ID) assigned at creation time. The CDMI object ID is a string with requirements * unique object identifier (ID) assigned at creation time. The CDMI object
* for how it is generated and how it obtains its uniqueness. Each offering that implements CDMI * ID is a string with requirements for how it is generated and how it
* is able to produce these identifiers without conflicting with other offerings. * obtains its uniqueness. Each offering that implements CDMI is able to
* produce these identifiers without conflicting with other offerings.
*
* note: CDMI Servers do not always support ObjectID tags, however
* downstream jclouds code does not handle null so we return a empty String
* instead.
*/ */
public String getObjectID() { public String getObjectID() {
return objectID; return (objectID == null) ? "" : objectID;
} }
/** /**
@ -117,15 +123,15 @@ public class CDMIObject {
} }
/** /**
* For objects in a container, the objectName field shall be returned. For objects not in a * For objects in a container, the objectName field shall be returned. For
* container (objects that are only accessible by ID), the objectName field shall not be * objects not in a container (objects that are only accessible by ID), the
* returned. * objectName field shall not be returned.
* *
* Name of the object * Name of the object
*/ */
@Nullable @Nullable
public String getObjectName() { public String getObjectName() {
return objectName; return (objectName == null) ? "" : objectName;
} }
@Override @Override
@ -135,7 +141,8 @@ public class CDMIObject {
if (o == null || getClass() != o.getClass()) if (o == null || getClass() != o.getClass())
return false; return false;
CDMIObject that = CDMIObject.class.cast(o); CDMIObject that = CDMIObject.class.cast(o);
return equal(this.objectID, that.objectID) && equal(this.objectName, that.objectName) return equal(this.objectID, that.objectID)
&& equal(this.objectName, that.objectName)
&& equal(this.objectType, that.objectType); && equal(this.objectType, that.objectType);
} }
@ -159,7 +166,7 @@ public class CDMIObject {
} }
protected ToStringHelper string() { protected ToStringHelper string() {
return Objects.toStringHelper("").add("objectID", objectID).add("objectName", objectName).add("objectType", return Objects.toStringHelper("").add("objectID", objectID)
objectType); .add("objectName", objectName).add("objectType", objectType);
} }
} }

View File

@ -21,9 +21,15 @@ package org.jclouds.snia.cdmi.v1.domain;
import static com.google.common.base.Objects.equal; import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.jclouds.domain.JsonBall;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper; import com.google.common.base.Objects.ToStringHelper;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
@ -32,7 +38,7 @@ import com.google.common.collect.Maps;
/** /**
* *
* @author Adrian Cole * @author Kenneth Nagin
*/ */
public class Container extends CDMIObject { public class Container extends CDMIObject {
@ -45,31 +51,35 @@ public class Container extends CDMIObject {
return builder().fromContainer(this); return builder().fromContainer(this);
} }
public static class Builder<B extends Builder<B>> extends CDMIObject.Builder<B> { public static class Builder<B extends Builder<B>> extends
CDMIObject.Builder<B> {
private Set<String> children = ImmutableSet.of(); private Set<String> children = ImmutableSet.of();
private Map<String, String> metadata = Maps.newHashMap(); private Map<String, JsonBall> metadata = Maps.newHashMap();
/** /**
* @see Container#getChildren() * @see Container#getChildren()
*/ */
public B children(String... children) { public B children(String... children) {
return children(ImmutableSet.copyOf(checkNotNull(children, "children"))); return children(ImmutableSet.copyOf(checkNotNull(children,
"children")));
} }
/** /**
* @see Container#getChildren() * @see Container#getChildren()
*/ */
public B children(Set<String> children) { public B children(Set<String> children) {
this.children = ImmutableSet.copyOf(checkNotNull(children, "children")); this.children = ImmutableSet.copyOf(checkNotNull(children,
"children"));
return self(); return self();
} }
/** /**
* @see Container#getMetadata() * @see Container#getMetadata()
*/ */
public B metadata(Map<String, String> metadata) { public B metadata(Map<String, JsonBall> metadata) {
this.metadata = ImmutableMap.copyOf(checkNotNull(metadata, "metadata")); this.metadata = ImmutableMap.copyOf(checkNotNull(metadata,
"metadata"));
return self(); return self();
} }
@ -79,7 +89,8 @@ public class Container extends CDMIObject {
} }
public B fromContainer(Container in) { public B fromContainer(Container in) {
return fromCDMIObject(in).children(in.getChildren()).metadata(in.getMetadata()); return fromCDMIObject(in).children(in.getChildren()).metadata(
in.getMetadata());
} }
} }
@ -87,30 +98,116 @@ public class Container extends CDMIObject {
} }
private final Set<String> children; private final Set<String> children;
private final Map<String, String> metadata; private final Map<String, JsonBall> metadata;
private Map<String, String> userMetaDataIn;
private Map<String, String> systemMetaDataIn;
private List<Map<String, String>> aclMetaDataIn;
protected Container(Builder<?> builder) { protected Container(Builder<?> builder) {
super(builder); super(builder);
this.children = ImmutableSet.copyOf(checkNotNull(builder.children, "children")); this.children = ImmutableSet.copyOf(checkNotNull(builder.children,
this.metadata = ImmutableMap.copyOf(checkNotNull(builder.metadata, "metadata")); "children"));
this.metadata = ImmutableMap.copyOf(checkNotNull(builder.metadata,
"metadata"));
} }
/** /**
* Names of the children objects in the container object. Child container objects end with "/". * Names of the children objects in the container object. Child container
* objects end with "/".
*/ */
public Set<String> getChildren() { public Set<String> getChildren() {
return children; return children;
} }
/** /**
* Metadata for the container object. This field includes any user and data system metadata * Metadata for the container object. This field includes any user and
* specified in the request body metadata field, along with storage system metadata generated by * system metadata specified in the request body metadata field, along with
* the cloud storage system. * storage system metadata generated by the cloud storage system.
*/ */
public Map<String, String> getMetadata() { public Map<String, JsonBall> getMetadata() {
return metadata; return metadata;
} }
/**
* Parse Metadata for the container object from the original JsonBall.
* System metadata data is prefixed with cdmi. System ACL metadata data is
* prefixed with cdmi_acl
*
*/
private void parseMetadata() {
userMetaDataIn = new HashMap<String, String>();
systemMetaDataIn = new HashMap<String, String>();
aclMetaDataIn = new ArrayList<Map<String, String>>();
Iterator<String> keys = metadata.keySet().iterator();
while (keys.hasNext()) {
String key = keys.next();
JsonBall value = metadata.get(key);
if (key.startsWith("cdmi")) {
if (key.matches("cdmi_acl")) {
String[] cdmi_acl_array = value.toString().split("[{}]");
for (int i = 0; i < cdmi_acl_array.length; i++) {
if (!(cdmi_acl_array[i].startsWith("[")
|| cdmi_acl_array[i].startsWith("]") || cdmi_acl_array[i]
.startsWith(","))) {
HashMap<String, String> aclMap = new HashMap<String, String>();
String[] cdmi_acl_member = cdmi_acl_array[i]
.split(",");
for (String s : cdmi_acl_member) {
String cdmi_acl_key = s.substring(0,
s.indexOf(":"));
String cdmi_acl_value = s.substring(s
.indexOf(":") + 1);
cdmi_acl_value.replace('"', ' ').trim();
aclMap.put(cdmi_acl_key, cdmi_acl_value);
}
aclMetaDataIn.add(aclMap);
}
}
} else {
systemMetaDataIn.put(key, value.toString()
.replace('"', ' ').trim());
}
} else {
userMetaDataIn.put(key, value.toString().replace('"', ' ')
.trim());
}
}
}
/**
* Get User Metadata for the container object. This field includes any user
* metadata
*/
public Map<String, String> getUserMetadata() {
if (userMetaDataIn == null) {
parseMetadata();
}
return userMetaDataIn;
}
/**
* Get System Metadata for the container object excluding ACL related
* metadata
*/
public Map<String, String> getSystemMetadata() {
if (systemMetaDataIn == null) {
parseMetadata();
}
return systemMetaDataIn;
}
/**
* Get System Metadata for the container object excluding ACL related
* metadata
*/
public List<Map<String, String>> getACLMetadata() {
if (aclMetaDataIn == null) {
parseMetadata();
}
return aclMetaDataIn;
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) if (this == o)
@ -118,7 +215,8 @@ public class Container extends CDMIObject {
if (o == null || getClass() != o.getClass()) if (o == null || getClass() != o.getClass())
return false; return false;
Container that = Container.class.cast(o); Container that = Container.class.cast(o);
return super.equals(that) && equal(this.children, that.children) && equal(this.metadata, that.metadata); return super.equals(that) && equal(this.children, that.children)
&& equal(this.metadata, that.metadata);
} }
@Override @Override
@ -128,7 +226,8 @@ public class Container extends CDMIObject {
@Override @Override
public ToStringHelper string() { public ToStringHelper string() {
return super.string().add("children", children).add("metadata", metadata); return super.string().add("children", children)
.add("metadata", metadata);
} }
} }

View File

@ -19,9 +19,12 @@
package org.jclouds.snia.cdmi.v1.features; package org.jclouds.snia.cdmi.v1.features;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.ExceptionParser;
@ -40,7 +43,7 @@ import com.google.common.util.concurrent.ListenableFuture;
* Container Object Resource Operations * Container Object Resource Operations
* *
* @see ContainerClient * @see ContainerClient
* @author Adrian Cole * @author Kenneth Nagin
* @see <a href="http://www.snia.org/cdmi">api doc</a> * @see <a href="http://www.snia.org/cdmi">api doc</a>
*/ */
@SkipEncoding( { '/', '=' }) @SkipEncoding( { '/', '=' })
@ -57,4 +60,24 @@ public interface ContainerAsyncClient {
@Path("/{containerName}/") @Path("/{containerName}/")
ListenableFuture<Container> getContainer(@PathParam("containerName") String containerName); ListenableFuture<Container> getContainer(@PathParam("containerName") String containerName);
/**
* @see ContainerClient#createContainer
*/
@PUT
@Consumes( { ObjectTypes.CONTAINER, MediaType.APPLICATION_JSON })
@Produces( { ObjectTypes.CONTAINER})
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@Path("/{containerName}/")
ListenableFuture<Container> createContainer(@PathParam("containerName") String containerName);
/**
* @see ContainerClient#createContainer()
*/
@DELETE
// @Consumes( { ObjectTypes.CONTAINER, MediaType.APPLICATION_JSON })
@Consumes( MediaType.APPLICATION_JSON )
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@Path("/{containerName}/")
ListenableFuture<Void> deleteContainer(@PathParam("containerName") String containerName);
} }

View File

@ -27,12 +27,15 @@ import org.jclouds.snia.cdmi.v1.domain.Container;
* Container Object Resource Operations * Container Object Resource Operations
* *
* @see ContainerAsyncClient * @see ContainerAsyncClient
* @author Adrian Cole * @author Kenneth Nagin
* @see <a href="http://www.snia.org/cdmi">api doc</a> * @see <a href="http://www.snia.org/cdmi">api doc</a>
*/ */
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS) @Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
public interface ContainerClient { public interface ContainerClient {
Container createContainer(String containerName);
Container getContainer(String containerName); Container getContainer(String containerName);
void deleteContainer(String containerName);
} }

View File

@ -21,6 +21,10 @@ package org.jclouds.snia.cdmi.v1.features;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNotNull;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.jclouds.snia.cdmi.v1.ObjectTypes; import org.jclouds.snia.cdmi.v1.ObjectTypes;
import org.jclouds.snia.cdmi.v1.domain.Container; import org.jclouds.snia.cdmi.v1.domain.Container;
import org.jclouds.snia.cdmi.v1.internal.BaseCDMIClientLiveTest; import org.jclouds.snia.cdmi.v1.internal.BaseCDMIClientLiveTest;
@ -28,21 +32,49 @@ import org.testng.annotations.Test;
/** /**
* *
* @author Adrian Cole * @author Kenneth Nagin
*/ */
@Test(groups = "live", testName = "ContainerClientLiveTest") @Test(groups = "live", testName = "ContainerClientLiveTest")
public class ContainerClientLiveTest extends BaseCDMIClientLiveTest { public class ContainerClientLiveTest extends BaseCDMIClientLiveTest {
@Test @Test
public void testGetContainer() throws Exception { public void testCreateContainer() throws Exception {
String pContainerName = "MyContainer" + System.currentTimeMillis();
ContainerClient client = cdmiContext.getApi().getContainerClient(); ContainerClient client = cdmiContext.getApi().getContainerClient();
Container container = client.getContainer("TODO: figure out how to list containers"); Logger.getAnonymousLogger().info("createContainer: " + pContainerName);
Container container = client.createContainer(pContainerName);
assertNotNull(container); assertNotNull(container);
System.out.println(container);
Logger.getAnonymousLogger().info("getContainer: " + pContainerName);
container = client.getContainer(pContainerName);
assertNotNull(container);
System.out.println(container);
assertEquals(container.getObjectType(), ObjectTypes.CONTAINER); assertEquals(container.getObjectType(), ObjectTypes.CONTAINER);
assertNotNull(container.getObjectID()); assertNotNull(container.getObjectID());
assertNotNull(container.getObjectName()); assertNotNull(container.getObjectName());
assertEquals(container.getObjectName(), pContainerName + "/");
assertNotNull(container.getChildren()); assertNotNull(container.getChildren());
assertEquals(container.getChildren().isEmpty(), true);
System.out.println("Children: " + container.getChildren());
assertNotNull(container.getMetadata()); assertNotNull(container.getMetadata());
assertNotNull(container.getUserMetadata());
System.out.println("UserMetaData: " + container.getUserMetadata());
assertNotNull(container.getSystemMetadata());
System.out.println("SystemMetaData: " + container.getSystemMetadata());
assertNotNull(container.getACLMetadata());
List<Map<String, String>> aclMetadataOut = container.getACLMetadata();
System.out.println("ACLMetaData: ");
for (Map<String, String> aclMap : aclMetadataOut) {
System.out.println(aclMap);
}
container = client.getContainer("/");
System.out.println("root container: " + container);
assertEquals(container.getChildren().contains(pContainerName + "/"), true);
Logger.getAnonymousLogger().info("deleteContainer: " + pContainerName);
client.deleteContainer(pContainerName);
container = client.getContainer("/");
System.out.println("root container: " + container);
assertEquals(container.getChildren().contains(pContainerName + "/"), false);
} }
} }

View File

@ -21,6 +21,7 @@ package org.jclouds.snia.cdmi.v1.parse;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import org.jclouds.domain.JsonBall;
import org.jclouds.json.BaseItemParserTest; import org.jclouds.json.BaseItemParserTest;
import org.jclouds.snia.cdmi.v1.domain.Container; import org.jclouds.snia.cdmi.v1.domain.Container;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -30,7 +31,7 @@ import com.google.common.collect.ImmutableSet;
/** /**
* *
* @author Adrian Cole * @author Kenneth Nagin
*/ */
@Test(groups = "unit", testName = "ParseContainerTest") @Test(groups = "unit", testName = "ParseContainerTest")
public class ParseContainerTest extends BaseItemParserTest<Container> { public class ParseContainerTest extends BaseItemParserTest<Container> {
@ -47,8 +48,8 @@ public class ParseContainerTest extends BaseItemParserTest<Container> {
.objectType("application/cdmi-container") .objectType("application/cdmi-container")
.objectID("00007E7F00102E230ED82694DAA975D2") .objectID("00007E7F00102E230ED82694DAA975D2")
.objectName("MyContainer/") .objectName("MyContainer/")
.metadata(ImmutableMap.<String, String>builder() .metadata(ImmutableMap.<String, JsonBall>builder()
.put("cdmi_size", "83") .put("cdmi_size", new JsonBall("\"83\""))
.build()) .build())
.children(ImmutableSet.<String>builder() .children(ImmutableSet.<String>builder()
.add("MyDataObject.txt") .add("MyDataObject.txt")