Issue 188: base impl of cdmi

This commit is contained in:
Adrian Cole 2012-04-24 17:38:39 -07:00
parent 1f7211d32d
commit 058213dd20
37 changed files with 2057 additions and 0 deletions

135
labs/cdmi/pom.xml Normal file
View File

@ -0,0 +1,135 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to jclouds, Inc. (jclouds) under one or more
contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. jclouds licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-project</artifactId>
<version>1.5.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds.labs</groupId>
<artifactId>cdmi</artifactId>
<name>jcloud cdmi api</name>
<description>jclouds components to access an implementation of SNIA CDMI</description>
<packaging>bundle</packaging>
<properties>
<test.cdmi.endpoint>http://localhost:8080</test.cdmi.endpoint>
<test.cdmi.api-version>1.0.1</test.cdmi.api-version>
<test.cdmi.build-version></test.cdmi.build-version>
<test.cdmi.identity>tenantId:IDENTITY</test.cdmi.identity>
<test.cdmi.credential>FIXME_CREDENTIALS</test.cdmi.credential>
<jclouds.blobstore.httpstream.url>FIXME_HTTPURL</jclouds.blobstore.httpstream.url>
<jclouds.blobstore.httpstream.md5>FIXME_HTTPMD5</jclouds.blobstore.httpstream.md5>
</properties>
<dependencies>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-blobstore</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-blobstore</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-slf4j</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>live</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<systemPropertyVariables>
<test.cdmi.endpoint>${test.cdmi.endpoint}</test.cdmi.endpoint>
<test.cdmi.api-version>${test.cdmi.api-version}</test.cdmi.api-version>
<test.cdmi.build-version>${test.cdmi.build-version}</test.cdmi.build-version>
<test.cdmi.identity>${test.cdmi.identity}</test.cdmi.identity>
<test.cdmi.credential>${test.cdmi.credential}</test.cdmi.credential>
<jclouds.blobstore.httpstream.url>${jclouds.blobstore.httpstream.url}</jclouds.blobstore.httpstream.url>
<jclouds.blobstore.httpstream.md5>${jclouds.blobstore.httpstream.md5}</jclouds.blobstore.httpstream.md5>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.snia.cdmi.v1*;version="${project.version}"</Export-Package>
<Import-Package>
org.jclouds.blobstore.internal;version="${project.version}",
org.jclouds.rest.internal;version="${project.version}",
org.jclouds*;version="${project.version}",
*
</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,93 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1;
import java.net.URI;
import java.util.Properties;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.BaseRestApiMetadata;
import org.jclouds.snia.cdmi.v1.config.CDMIRestClientModule;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken;
import com.google.inject.Module;
/**
* Implementation of {@link ApiMetadata} for CDMI 1.0.1 API
*
* @author Adrian Cole
*/
public class CDMIApiMetadata extends BaseRestApiMetadata {
/** The serialVersionUID */
private static final long serialVersionUID = 6725672099385580694L;
public static final TypeToken<RestContext<CDMIClient, CDMIAsyncClient>> CONTEXT_TOKEN = new TypeToken<RestContext<CDMIClient, CDMIAsyncClient>>() {
private static final long serialVersionUID = -5070937833892503232L;
};
@Override
public Builder toBuilder() {
return new Builder().fromApiMetadata(this);
}
public CDMIApiMetadata() {
this(new Builder());
}
protected CDMIApiMetadata(Builder builder) {
super(builder);
}
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
return properties;
}
public static class Builder extends BaseRestApiMetadata.Builder {
protected Builder() {
super(CDMIClient.class, CDMIAsyncClient.class);
id("cdmi")
.name("SNIA CDMI API")
.identityName("tenantId:user")
.credentialName("password")
.documentation(URI.create("http://www.snia.org/cdmi"))
.version("1.0.1")
.defaultEndpoint("http://localhost:8080")
.defaultProperties(CDMIApiMetadata.defaultProperties())
.defaultModules(ImmutableSet.<Class<? extends Module>> of(CDMIRestClientModule.class));
}
@Override
public CDMIApiMetadata build() {
return new CDMIApiMetadata(this);
}
@Override
public Builder fromApiMetadata(ApiMetadata in) {
super.fromApiMetadata(in);
return this;
}
}
}

View File

@ -0,0 +1,53 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.snia.cdmi.v1.features.ContainerAsyncClient;
import org.jclouds.snia.cdmi.v1.features.DataAsyncClient;
import org.jclouds.snia.cdmi.v1.features.DomainAsyncClient;
/**
* Provides asynchronous access to CDMI via their REST API.
* <p/>
*
* @see CDMIClient
* @see <a href="http://www.snia.org/cdmi">api doc</a>
* @author Adrian Cole
*/
public interface CDMIAsyncClient {
/**
* Provides asynchronous access to Domain Object Resource Operations.
*/
@Delegate
DomainAsyncClient getDomainClient();
/**
* Provides asynchronous access to Container Object Resource Operations.
*/
@Delegate
ContainerAsyncClient getContainerClient();
/**
* Provides asynchronous access to Data Object Resource Operations.
*/
@Delegate
DataAsyncClient getDataClient();
}

View File

@ -0,0 +1,57 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1;
import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.snia.cdmi.v1.features.ContainerClient;
import org.jclouds.snia.cdmi.v1.features.DataClient;
import org.jclouds.snia.cdmi.v1.features.DomainClient;
/**
* Provides synchronous access to CDMI.
* <p/>
*
* @see CDMIAsyncClient
* @see <a href="http://www.snia.org/cdmi">api doc</a>
* @author Adrian Cole
*/
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
public interface CDMIClient {
/**
* Provides synchronous access to Domain Object Resource Operations.
*/
@Delegate
DomainClient getDomainClient();
/**
* Provides synchronous access to Container Object Resource Operations.
*/
@Delegate
ContainerClient getContainerClient();
/**
* Provides synchronous access to Data Object Resource Operations.
*/
@Delegate
DataClient getDataClient();
}

View File

@ -0,0 +1,31 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1;
/**
* Object Types used in CDMI.
*
* @see javax.ws.rs.core.MediaType;
*/
public interface ObjectTypes {
public static final String CONTAINER = "application/cdmi-container";
}

View File

@ -0,0 +1,28 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.config;
/**
* Configuration properties and constants used in SNIA CDMI connections.
*
* @author Adrian Cole
*/
public class CDMIProperties {
}

View File

@ -0,0 +1,63 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.config;
import java.util.Map;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule;
import org.jclouds.snia.cdmi.v1.CDMIAsyncClient;
import org.jclouds.snia.cdmi.v1.CDMIClient;
import org.jclouds.snia.cdmi.v1.features.ContainerAsyncClient;
import org.jclouds.snia.cdmi.v1.features.ContainerClient;
import org.jclouds.snia.cdmi.v1.features.DataAsyncClient;
import org.jclouds.snia.cdmi.v1.features.DataClient;
import org.jclouds.snia.cdmi.v1.features.DomainAsyncClient;
import org.jclouds.snia.cdmi.v1.features.DomainClient;
import org.jclouds.snia.cdmi.v1.handlers.CDMIErrorHandler;
import com.google.common.collect.ImmutableMap;
/**
* Configures the CDMI connection.
*
* @author Adrian Cole
*/
@ConfiguresRestClient
public class CDMIRestClientModule extends RestClientModule<CDMIClient, CDMIAsyncClient> {
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder().put(
DomainClient.class, DomainAsyncClient.class).put(ContainerClient.class, ContainerAsyncClient.class).put(
DataClient.class, DataAsyncClient.class).build();
public CDMIRestClientModule() {
super(DELEGATE_MAP);
}
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(CDMIErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(CDMIErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(CDMIErrorHandler.class);
}
}

View File

@ -0,0 +1,165 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.domain;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
/**
* The base type for all objects in the CDMI model.
*
* @author Adrian Cole
*/
public class CDMIObject {
public static Builder<?> builder() {
return new ConcreteBuilder();
}
public Builder<?> toBuilder() {
return builder().fromCDMIObject(this);
}
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
}
public static abstract class Builder<B extends Builder<B>> {
private String objectID;
private String objectType;
private String objectName;
@SuppressWarnings("unchecked")
protected B self() {
return (B) this;
}
/**
* @see CDMIObject#getObjectID()
*/
public B objectID(String objectID) {
this.objectID = objectID;
return self();
}
/**
* @see CDMIObject#getObjectType()
*/
public B objectType(String objectType) {
this.objectType = objectType;
return self();
}
/**
* @see CDMIObject#getObjectName()
*/
public B objectName(String objectName) {
this.objectName = objectName;
return self();
}
public CDMIObject build() {
return new CDMIObject(this);
}
protected B fromCDMIObject(CDMIObject in) {
return objectID(in.getObjectID()).objectType(in.getObjectType()).objectName(in.getObjectName());
}
}
private final String objectID;
private final String objectType;
private final String objectName;
protected CDMIObject(Builder<?> builder) {
this.objectID = checkNotNull(builder.objectID, "objectID");
this.objectType = checkNotNull(builder.objectType, "objectType");
this.objectName = builder.objectName;
}
/**
* Object ID of the object <br/>
* Every object stored within a CDMI-compliant system shall have a globally unique object
* identifier (ID) assigned at creation time. The CDMI object ID is a string with requirements
* for how it is generated and how it obtains its uniqueness. Each offering that implements CDMI
* is able to produce these identifiers without conflicting with other offerings.
*/
public String getObjectID() {
return objectID;
}
/**
*
* type of the object
*/
public String getObjectType() {
return objectType;
}
/**
* For objects in a container, the objectName field shall be returned. For objects not in a
* container (objects that are only accessible by ID), the objectName field shall not be
* returned.
*
* Name of the object
*/
@Nullable
public String getObjectName() {
return objectName;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
CDMIObject that = CDMIObject.class.cast(o);
return equal(this.objectID, that.objectID) && equal(this.objectName, that.objectName)
&& equal(this.objectType, that.objectType);
}
public boolean clone(Object o) {
if (this == o)
return false;
if (o == null || getClass() != o.getClass())
return false;
CDMIObject that = CDMIObject.class.cast(o);
return equal(this.objectType, that.objectType);
}
@Override
public int hashCode() {
return Objects.hashCode(objectID, objectName, objectType);
}
@Override
public String toString() {
return string().toString();
}
protected ToStringHelper string() {
return Objects.toStringHelper("").add("objectID", objectID).add("objectName", objectName).add("objectType",
objectType);
}
}

View File

@ -0,0 +1,134 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.domain;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import java.util.Set;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
/**
*
* @author Adrian Cole
*/
public class Container extends CDMIObject {
public static Builder<?> builder() {
return new ConcreteBuilder();
}
@Override
public Builder<?> toBuilder() {
return builder().fromContainer(this);
}
public static class Builder<B extends Builder<B>> extends CDMIObject.Builder<B> {
private Set<String> children = ImmutableSet.of();
private Map<String, String> metadata = Maps.newHashMap();
/**
* @see Container#getChildren()
*/
public B children(String... children) {
return children(ImmutableSet.copyOf(checkNotNull(children, "children")));
}
/**
* @see Container#getChildren()
*/
public B children(Set<String> children) {
this.children = ImmutableSet.copyOf(checkNotNull(children, "children"));
return self();
}
/**
* @see Container#getMetadata()
*/
public B metadata(Map<String, String> metadata) {
this.metadata = ImmutableMap.copyOf(checkNotNull(metadata, "metadata"));
return self();
}
@Override
public Container build() {
return new Container(this);
}
public B fromContainer(Container in) {
return fromCDMIObject(in).children(in.getChildren()).metadata(in.getMetadata());
}
}
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
}
private final Set<String> children;
private final Map<String, String> metadata;
protected Container(Builder<?> builder) {
super(builder);
this.children = ImmutableSet.copyOf(checkNotNull(builder.children, "children"));
this.metadata = ImmutableMap.copyOf(checkNotNull(builder.metadata, "metadata"));
}
/**
* Names of the children objects in the container object. Child container objects end with "/".
*/
public Set<String> getChildren() {
return children;
}
/**
* Metadata for the container object. This field includes any user and data system metadata
* specified in the request body metadata field, along with storage system metadata generated by
* the cloud storage system.
*/
public Map<String, String> getMetadata() {
return metadata;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Container that = Container.class.cast(o);
return super.equals(that) && equal(this.children, that.children) && equal(this.metadata, that.metadata);
}
@Override
public int hashCode() {
return Objects.hashCode(super.hashCode(), children, metadata);
}
@Override
public ToStringHelper string() {
return super.string().add("children", children).add("metadata", metadata);
}
}

View File

@ -0,0 +1,60 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.features;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.snia.cdmi.v1.ObjectTypes;
import org.jclouds.snia.cdmi.v1.domain.Container;
import org.jclouds.snia.cdmi.v1.filters.BasicAuthenticationAndTenantId;
import org.jclouds.snia.cdmi.v1.filters.StripExtraAcceptHeader;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Container Object Resource Operations
*
* @see ContainerClient
* @author Adrian Cole
* @see <a href="http://www.snia.org/cdmi">api doc</a>
*/
@SkipEncoding( { '/', '=' })
@RequestFilters( { BasicAuthenticationAndTenantId.class, StripExtraAcceptHeader.class })
@Headers(keys="X-CDMI-Specification-Version", values = "{jclouds.api-version}")
public interface ContainerAsyncClient {
/**
* @see ContainerClient#listContainers()
*/
@GET
@Consumes( { ObjectTypes.CONTAINER, MediaType.APPLICATION_JSON })
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@Path("/{containerName}/")
ListenableFuture<Container> getContainer(@PathParam("containerName") String containerName);
}

View File

@ -0,0 +1,38 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.features;
import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
import org.jclouds.snia.cdmi.v1.domain.Container;
/**
* Container Object Resource Operations
*
* @see ContainerAsyncClient
* @author Adrian Cole
* @see <a href="http://www.snia.org/cdmi">api doc</a>
*/
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
public interface ContainerClient {
Container getContainer(String containerName);
}

View File

@ -0,0 +1,39 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.features;
import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.snia.cdmi.v1.filters.BasicAuthenticationAndTenantId;
import org.jclouds.snia.cdmi.v1.filters.StripExtraAcceptHeader;
/**
* Data Object Resource Operations
*
* @see DataClient
* @author Adrian Cole
* @see <a href="http://www.snia.org/cdmi">api doc</a>
*/
@SkipEncoding( { '/', '=' })
@RequestFilters( { BasicAuthenticationAndTenantId.class, StripExtraAcceptHeader.class })
@Headers(keys="X-CDMI-Specification-Version", values = "{jclouds.api-version}")
public interface DataAsyncClient {
}

View File

@ -0,0 +1,35 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.features;
import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
/**
* Data Object Resource Operations
*
* @see DataAsyncClient
* @author Adrian Cole
* @see <a href="http://www.snia.org/cdmi">api doc</a>
*/
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
public interface DataClient {
}

View File

@ -0,0 +1,40 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.features;
import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.snia.cdmi.v1.filters.BasicAuthenticationAndTenantId;
import org.jclouds.snia.cdmi.v1.filters.StripExtraAcceptHeader;
/**
* Domain Object Resource Operations
*
* @see DomainClient
* @author Adrian Cole
* @see <a href="http://www.snia.org/cdmi">api doc</a>
*/
@SkipEncoding( { '/', '=' })
@RequestFilters( { BasicAuthenticationAndTenantId.class, StripExtraAcceptHeader.class })
@Headers(keys="X-CDMI-Specification-Version", values = "{jclouds.api-version}")
public interface DomainAsyncClient {
}

View File

@ -0,0 +1,36 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.features;
import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
/**
* Domain Object Resource Operations
*
* @see DomainAsyncClient
* @author Adrian Cole
* @see <a href="http://www.snia.org/cdmi">api doc</a>
*/
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
public interface DomainClient {
}

View File

@ -0,0 +1,62 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.filters;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.crypto.Crypto;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.http.utils.ModifyRequest;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.annotations.Credential;
import org.jclouds.rest.annotations.Identity;
/**
* Uses Basic Authentication to sign the request, and adds the {@code TID} header.
*
* @see <a href= "http://en.wikipedia.org/wiki/Basic_access_authentication" />
* @author Adrian Cole
*
*/
@Singleton
public class BasicAuthenticationAndTenantId implements HttpRequestFilter {
private final String tenantId;
private final BasicAuthentication basicAuthentication;
@Inject
public BasicAuthenticationAndTenantId(@Identity String tenantIdAndUsername, @Credential String password,
Crypto crypto) {
if (tenantIdAndUsername.indexOf(':') == -1) {
throw new AuthorizationException(String.format("Identity %s does not match format tenantId:username",
tenantIdAndUsername), null);
}
this.tenantId = tenantIdAndUsername.substring(0, tenantIdAndUsername.indexOf(':'));
String username = tenantIdAndUsername.substring(tenantIdAndUsername.indexOf(':') + 1);
this.basicAuthentication = new BasicAuthentication(username, password, crypto);
}
@Override
public HttpRequest filter(HttpRequest request) throws HttpException {
return basicAuthentication.filter(ModifyRequest.replaceHeader(request, "TID", tenantId));
}
}

View File

@ -0,0 +1,43 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.filters;
import javax.inject.Singleton;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.utils.ModifyRequest;
/**
* current CDMI spec doesn't indicate the form of the response. It would be nice, if it could take 2
* {@code Accept} headers. Until then, let's strip off the mediaType header, which we use to ensure
* responses are parsed with json.
*
* @author Adrian Cole
*
*/
@Singleton
public class StripExtraAcceptHeader implements HttpRequestFilter {
@Override
public HttpRequest filter(HttpRequest request) throws HttpException {
return ModifyRequest.replaceHeader(request, "Accept", request.getFirstHeaderOrNull("Accept"));
}
}

View File

@ -0,0 +1,82 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.handlers;
import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Singleton;
import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException;
import org.jclouds.rest.AuthorizationException;
/**
* This will parse and set an appropriate exception on the command data.
*
* @author Adrian Cole
*
*/
// TODO: is there error spec someplace? let's type errors, etc.
@Singleton
public class CDMIErrorHandler implements HttpErrorHandler {
public static final String PREFIX = "^/v[0-9][^/]*/[a-zA-Z]+_[^/]+/";
public static final Pattern CONTAINER_PATH = Pattern.compile(PREFIX + "([^/]+)$");
public static final Pattern CONTAINER_KEY_PATH = Pattern.compile(PREFIX + "([^/]+)/(.*)");
public void handleError(HttpCommand command, HttpResponse response) {
// it is important to always read fully and close streams
byte[] data = closeClientButKeepContentStream(response);
String message = data != null ? new String(data) : null;
Exception exception = message != null ? new HttpResponseException(command, response, message)
: new HttpResponseException(command, response);
message = message != null ? message : String.format("%s -> %s", command.getCurrentRequest().getRequestLine(),
response.getStatusLine());
switch (response.getStatusCode()) {
case 401:
exception = new AuthorizationException(exception.getMessage(), exception);
break;
case 404:
if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
String path = command.getCurrentRequest().getEndpoint().getPath();
Matcher matcher = CONTAINER_PATH.matcher(path);
Exception oldException = exception;
if (matcher.find()) {
exception = new ContainerNotFoundException(matcher.group(1), message);
exception.initCause(oldException);
} else {
matcher = CONTAINER_KEY_PATH.matcher(path);
if (matcher.find()) {
exception = new KeyNotFoundException(matcher.group(1), matcher.group(2), message);
exception.initCause(oldException);
}
}
}
break;
}
command.setException(exception);
}
}

View File

@ -0,0 +1,78 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.options;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import org.jclouds.http.options.BaseHttpRequestOptions;
/**
* Contains options supported in the REST API for the GET container operation. <h2>
*/
public class ListContainersOptions extends BaseHttpRequestOptions {
public static final ListContainersOptions NONE = new ListContainersOptions();
/**
* Given a string value x, return data names greater in value than the specified marker.
*/
public ListContainersOptions marker(String marker) {
queryParameters.put("marker", checkNotNull(marker, "marker"));
return this;
}
public String getMarker() {
return getFirstQueryOrNull("marker");
}
/**
* For an integer value n, limits the number of results to n values.
*/
public ListContainersOptions limit(int limit) {
checkState(limit >= 0, "limit must be >= 0");
checkState(limit <= 10000, "limit must be <= 10000");
queryParameters.put("limit", Integer.toString(limit));
return this;
}
public int getLimit() {
String val = getFirstQueryOrNull("limit");
return val != null ? new Integer(val) : 10000;
}
public static class Builder {
/**
* @see ListContainersOptions#marker(String)
*/
public static ListContainersOptions marker(String marker) {
ListContainersOptions options = new ListContainersOptions();
return options.marker(marker);
}
/**
* @see ListContainersOptions#limit(int)
*/
public static ListContainersOptions limit(int limit) {
ListContainersOptions options = new ListContainersOptions();
return options.limit(limit);
}
}
}

View File

@ -0,0 +1 @@
org.jclouds.snia.cdmi.v1.CDMIApiMetadata

View File

@ -0,0 +1,38 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1;
import org.jclouds.View;
import org.jclouds.apis.internal.BaseApiMetadataTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "CDMIApiMetadataTest")
// public class CDMIApiMetadataTest extends BaseBlobStoreApiMetadataTest {
public class CDMIApiMetadataTest extends BaseApiMetadataTest {
public CDMIApiMetadataTest() {
super(new CDMIApiMetadata(), ImmutableSet.<TypeToken<? extends View>> of());
}
}

View File

@ -0,0 +1,120 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reportMatcher;
import static org.easymock.EasyMock.verify;
import java.net.URI;
import org.easymock.IArgumentMatcher;
import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.io.Payloads;
import org.jclouds.snia.cdmi.v1.handlers.CDMIErrorHandler;
import org.jclouds.util.Strings2;
import org.testng.annotations.Test;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "CDMIErrorHandlerTest")
public class CDMIErrorHandlerTest {
@Test
public void test404SetsKeyNotFoundExceptionMosso() {
assertCodeMakes("HEAD", URI
.create("http://host/v1/MossoCloudFS_7064cdb1d49d4dcba3c899ac33e8409d/adriancole-blobstore1/key"), 404,
"Not Found", "", KeyNotFoundException.class);
}
@Test
public void test404SetsKeyNotFoundExceptionCDMI() {
assertCodeMakes("HEAD", URI
.create("http://67.202.39.175:8080/v1/AUTH_7064cdb1d49d4dcba3c899ac33e8409d/adriancole-blobstore1/key"),
404, "Not Found", "", KeyNotFoundException.class);
}
@Test
public void test404SetsContainerNotFoundExceptionMosso() {
assertCodeMakes("HEAD", URI
.create("http://host/v1/MossoCloudFS_7064cdb1d49d4dcba3c899ac33e8409d/adriancole-blobstore1"), 404,
"Not Found", "", ContainerNotFoundException.class);
}
@Test
public void test404SetsContainerNotFoundExceptionCDMI() {
assertCodeMakes("HEAD", URI
.create("http://67.202.39.175:8080/v1/AUTH_7064cdb1d49d4dcba3c899ac33e8409d/adriancole-blobstore1"),
404, "Not Found", "", ContainerNotFoundException.class);
}
private void assertCodeMakes(String method, URI uri, int statusCode, String message, String content,
Class<? extends Exception> expected) {
assertCodeMakes(method, uri, statusCode, message, "text/plain", content, expected);
}
private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType,
String content, Class<? extends Exception> expected) {
CDMIErrorHandler function = new CDMIErrorHandler();
HttpCommand command = createMock(HttpCommand.class);
HttpRequest request = new HttpRequest(method, uri);
HttpResponse response = new HttpResponse(statusCode, message, Payloads.newInputStreamPayload(Strings2
.toInputStream(content)));
response.getPayload().getContentMetadata().setContentType(contentType);
expect(command.getCurrentRequest()).andReturn(request).atLeastOnce();
command.setException(classEq(expected));
replay(command);
function.handleError(command, response);
verify(command);
}
public static Exception classEq(final Class<? extends Exception> in) {
reportMatcher(new IArgumentMatcher() {
@Override
public void appendTo(StringBuffer buffer) {
buffer.append("classEq(");
buffer.append(in);
buffer.append(")");
}
@Override
public boolean matches(Object arg) {
return arg.getClass() == in;
}
});
return null;
}
}

View File

@ -0,0 +1,66 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.features;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import org.jclouds.crypto.CryptoStreams;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.snia.cdmi.v1.CDMIClient;
import org.jclouds.snia.cdmi.v1.internal.BaseCDMIClientExpectTest;
import org.jclouds.snia.cdmi.v1.parse.ParseContainerTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMultimap;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ContainerAsyncClientTest")
public class ContainerClientExpectTest extends BaseCDMIClientExpectTest {
public void testGetContainerWhenResponseIs2xx() throws Exception {
HttpRequest getContainer = HttpRequest
.builder()
.method("GET")
.endpoint(URI.create("http://localhost:8080/MyContainer/"))
.headers(ImmutableMultimap.<String, String> builder()
.put("X-CDMI-Specification-Version", "1.0.1")
.put("Accept", "application/cdmi-container")
.put("TID", "tenantId")
.put("Authorization", "Basic " + CryptoStreams.base64("username:password".getBytes()))
.build())
.build();
HttpResponse getContainerResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/container.json")).build();
CDMIClient clientWhenContainersExist = requestSendsResponse(getContainer, getContainerResponse);
assertEquals(
clientWhenContainersExist.getContainerClient().getContainer("MyContainer"),
new ParseContainerTest().expected());
}
}

View File

@ -0,0 +1,48 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.features;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import org.jclouds.snia.cdmi.v1.ObjectTypes;
import org.jclouds.snia.cdmi.v1.domain.Container;
import org.jclouds.snia.cdmi.v1.internal.BaseCDMIClientLiveTest;
import org.testng.annotations.Test;
/**
*
* @author Adrian Cole
*/
@Test(groups = "live", testName = "ContainerClientLiveTest")
public class ContainerClientLiveTest extends BaseCDMIClientLiveTest {
@Test
public void testGetContainer() throws Exception {
ContainerClient client = cdmiContext.getApi().getContainerClient();
Container container = client.getContainer("TODO: figure out how to list containers");
assertNotNull(container);
assertEquals(container.getObjectType(), ObjectTypes.CONTAINER);
assertNotNull(container.getObjectID());
assertNotNull(container.getObjectName());
assertNotNull(container.getChildren());
assertNotNull(container.getMetadata());
}
}

View File

@ -0,0 +1,30 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.features;
import org.jclouds.snia.cdmi.v1.internal.BaseCDMIClientExpectTest;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "DataAsyncClientTest")
public class DataClientExpectTest extends BaseCDMIClientExpectTest {
}

View File

@ -0,0 +1,30 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.features;
import org.jclouds.snia.cdmi.v1.internal.BaseCDMIClientLiveTest;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "live", testName = "DataClientLiveTest")
public class DataClientLiveTest extends BaseCDMIClientLiveTest {
}

View File

@ -0,0 +1,30 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unles required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either expres or implied. See the License for the
* specific language governing permisions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.features;
import org.jclouds.snia.cdmi.v1.internal.BaseCDMIClientExpectTest;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "DomainClientExpectTest")
public class DomainClientExpectTest extends BaseCDMIClientExpectTest {
}

View File

@ -0,0 +1,30 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.features;
import org.jclouds.snia.cdmi.v1.internal.BaseCDMIClientLiveTest;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "live", testName = "ContainerClientLiveTest")
public class DomainClientLiveTest extends BaseCDMIClientLiveTest {
}

View File

@ -0,0 +1,39 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.internal;
import java.util.Properties;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.snia.cdmi.v1.CDMIAsyncClient;
import com.google.common.base.Function;
import com.google.inject.Module;
/**
* Base class for writing KeyStone Rest Client Expect tests
*
* @author Adrian Cole
*/
public class BaseCDMIAsyncClientExpectTest extends BaseCDMIExpectTest<CDMIAsyncClient> {
public CDMIAsyncClient createClient(Function<HttpRequest, HttpResponse> fn, Module module, Properties props) {
return createInjector(fn, module, props).getInstance(CDMIAsyncClient.class);
}
}

View File

@ -0,0 +1,30 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.internal;
import org.jclouds.snia.cdmi.v1.CDMIClient;
/**
* Base class for writing KeyStone Rest Client Expect tests
*
* @author Adrian Cole
*/
public class BaseCDMIClientExpectTest extends BaseCDMIExpectTest<CDMIClient> {
}

View File

@ -0,0 +1,64 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.internal;
import org.jclouds.apis.BaseContextLiveTest;
import org.jclouds.rest.RestContext;
import org.jclouds.snia.cdmi.v1.CDMIApiMetadata;
import org.jclouds.snia.cdmi.v1.CDMIAsyncClient;
import org.jclouds.snia.cdmi.v1.CDMIClient;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import com.google.common.reflect.TypeToken;
/**
* Tests behavior of {@code CDMIClient}
*
* @author Adrian Cole
*/
@Test(groups = "live")
public class BaseCDMIClientLiveTest extends BaseContextLiveTest<RestContext<CDMIClient, CDMIAsyncClient>> {
public BaseCDMIClientLiveTest() {
provider = "cdmi";
}
protected RestContext<CDMIClient, CDMIAsyncClient> cdmiContext;
@BeforeGroups(groups = { "integration", "live" })
@Override
public void setupContext() {
super.setupContext();
cdmiContext = context;
}
@AfterGroups(groups = "live")
protected void tearDown() {
if (cdmiContext != null)
cdmiContext.close();
}
@Override
protected TypeToken<RestContext<CDMIClient, CDMIAsyncClient>> contextType() {
return CDMIApiMetadata.CONTEXT_TOKEN;
}
}

View File

@ -0,0 +1,36 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.internal;
import org.jclouds.rest.internal.BaseRestClientExpectTest;
/**
* Base class for writing CDMI Expect tests
*
* @author Adrian Cole
*/
public class BaseCDMIExpectTest<T> extends BaseRestClientExpectTest<T> {
public BaseCDMIExpectTest() {
provider = "cdmi";
// now, createContext arg will need tenant prefix
identity = "tenantId:username";
credential = "password";
}
}

View File

@ -0,0 +1,96 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.options;
import static org.jclouds.snia.cdmi.v1.options.ListContainersOptions.Builder.limit;
import static org.jclouds.snia.cdmi.v1.options.ListContainersOptions.Builder.marker;
import static org.testng.Assert.assertEquals;
import java.util.Collections;
import org.jclouds.http.options.HttpRequestOptions;
import org.testng.annotations.Test;
/**
* Tests possible uses of ListContainerOptions and ListContainerOptions.Builder.*
*
* @author Adrian Cole
*/
@Test(testName = "ListContainersOptionsTest")
public class ListContainersOptionsTest {
@Test
public void testAssignability() {
assert HttpRequestOptions.class.isAssignableFrom(ListContainersOptions.class);
assert !String.class.isAssignableFrom(ListContainersOptions.class);
}
@Test
public void testNoOptionsQueryString() {
HttpRequestOptions options = new ListContainersOptions();
assertEquals(options.buildQueryParameters().size(), 0);
}
@Test
public void testMarker() {
ListContainersOptions options = new ListContainersOptions();
options.marker("test");
assertEquals(options.buildQueryParameters().get("marker"), Collections.singletonList("test"));
}
@Test
public void testNullMarker() {
ListContainersOptions options = new ListContainersOptions();
assertEquals(options.buildQueryParameters().get("marker"), Collections.EMPTY_LIST);
}
@Test
public void testMarkerStatic() {
ListContainersOptions options = marker("test");
assertEquals(options.buildQueryParameters().get("marker"), Collections.singletonList("test"));
}
@Test(expectedExceptions = NullPointerException.class)
public void testMarkerNPE() {
marker(null);
}
@Test
public void testLimit() {
ListContainersOptions options = new ListContainersOptions();
options.limit(1000);
assertEquals(options.buildQueryParameters().get("limit"), Collections.singletonList("1000"));
}
@Test
public void testNullLimit() {
ListContainersOptions options = new ListContainersOptions();
assertEquals(options.buildQueryParameters().get("limit"), Collections.EMPTY_LIST);
}
@Test
public void testLimitStatic() {
ListContainersOptions options = limit(1000);
assertEquals(options.buildQueryParameters().get("limit"), Collections.singletonList("1000"));
}
@Test(expectedExceptions = IllegalStateException.class)
public void testLimitNegative() {
limit(-1);
}
}

View File

@ -0,0 +1,58 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.snia.cdmi.v1.parse;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
import org.jclouds.json.BaseItemParserTest;
import org.jclouds.snia.cdmi.v1.domain.Container;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ParseContainerTest")
public class ParseContainerTest extends BaseItemParserTest<Container> {
@Override
public String resource() {
return "/container.json";
}
@Override
@Consumes(MediaType.APPLICATION_JSON)
public Container expected() {
return Container.builder()
.objectType("application/cdmi-container")
.objectID("00007E7F00102E230ED82694DAA975D2")
.objectName("MyContainer/")
.metadata(ImmutableMap.<String, String>builder()
.put("cdmi_size", "83")
.build())
.children(ImmutableSet.<String>builder()
.add("MyDataObject.txt")
.build())
.build();
}
}

View File

@ -0,0 +1,17 @@
{
"objectType" : "application/cdmi-container",
"objectID" : "00007E7F00102E230ED82694DAA975D2",
"objectName" : "MyContainer/",
"parentURI" : "/",
"parentID" : "00007E7F0010128E42D87EE34F5A6560",
"domainURI" : "/cdmi_domains/MyDomain/",
"capabilitiesURI" : "/cdmi_capabilities/container/",
"completionStatus" : "Complete",
"metadata" : {
"cdmi_size" : "83"
},
"childrenrange" : "0-0",
"children" : [
"MyDataObject.txt"
]
}

View File

@ -0,0 +1,51 @@
<?xml version="1.0"?>
<configuration scan="false">
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>target/test-data/jclouds.log</file>
<encoder>
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
</encoder>
</appender>
<appender name="WIREFILE" class="ch.qos.logback.core.FileAppender">
<file>target/test-data/jclouds-wire.log</file>
<encoder>
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
</encoder>
</appender>
<appender name="BLOBSTOREFILE" class="ch.qos.logback.core.FileAppender">
<file>target/test-data/jclouds-blobstore.log</file>
<encoder>
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
</encoder>
</appender>
<root>
<level value="warn" />
</root>
<logger name="org.jclouds">
<level value="DEBUG" />
<appender-ref ref="FILE" />
</logger>
<logger name="jclouds.wire">
<level value="DEBUG" />
<appender-ref ref="WIREFILE" />
</logger>
<logger name="jclouds.headers">
<level value="DEBUG" />
<appender-ref ref="WIREFILE" />
</logger>
<logger name="jclouds.blobstore">
<level value="DEBUG" />
<appender-ref ref="BLOBSTOREFILE" />
</logger>
</configuration>

View File

@ -43,5 +43,6 @@
<module>carrenza-vcloud-director</module>
<module>openstack-swift</module>
<module>jenkins</module>
<module>cdmi</module>
</modules>
</project>