You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by za...@apache.org on 2015/04/07 23:33:00 UTC
[02/32] jclouds git commit: JCLOUDS-423 - Adds support for Rackspace Cloud Files API - Added support for CloudFilesApi/CDNApi - Added mock/live tests - Refactored listFirstPage() and listAt() API methods to list() and listWithOptions(…) - General Swift A
JCLOUDS-423 - Adds support for Rackspace Cloud Files API - Added support for CloudFilesApi/CDNApi - Added mock/live tests - Refactored listFirstPage() and listAt() API methods to list() and listWithOptions(…) - General Swift API cleanup: docs and tests - Added support for Internal URL - Updated JavaDocs and domain objects. - Added support for Cloud Files US
Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/2ca0dac7
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/2ca0dac7
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/2ca0dac7
Branch: refs/heads/master
Commit: 2ca0dac76c64c65d10e195496392d2b6c39a2e09
Parents:
Author: Jeremy Daggett <je...@rackspace.com>
Authored: Fri Feb 14 09:36:53 2014 -0800
Committer: Zack Shoylev <za...@rackspace.com>
Committed: Mon Mar 3 15:32:58 2014 -0600
----------------------------------------------------------------------
apis/rackspace-cloudfiles/README.md | 20 +
apis/rackspace-cloudfiles/pom.xml | 171 +++++++++
.../rackspace/cloudfiles/v1/CloudFilesApi.java | 50 +++
.../cloudfiles/v1/CloudFilesApiMetadata.java | 104 +++++
.../BindCDNPurgeEmailAddressesToHeaders.java | 56 +++
.../v1/config/CloudFilesHttpApiModule.java | 50 +++
.../cloudfiles/v1/domain/CDNContainer.java | 264 +++++++++++++
.../cloudfiles/v1/features/CDNApi.java | 205 ++++++++++
.../functions/ParseCDNContainerFromHeaders.java | 84 ++++
.../ParseCDNContainerURIFromHeaders.java | 45 +++
.../v1/functions/RegionToCDNEndpoint.java | 77 ++++
.../v1/handlers/CloudFilesErrorHandler.java | 91 +++++
.../v1/options/UpdateCDNContainerOptions.java | 163 ++++++++
.../v1/reference/CloudFilesHeaders.java | 58 +++
.../services/org.jclouds.apis.ApiMetadata | 18 +
.../cloudfiles/v1/CloudFilesApiLiveTest.java | 30 ++
.../v1/CloudFilesApiMetadataTest.java | 35 ++
...CDNPurgeEmailAddressesToHeadersMockTest.java | 77 ++++
...lesRegionScopedBlobStoreContextLiveTest.java | 39 ++
.../CloudFilesBlobIntegrationLiveTest.java | 39 ++
.../integration/CloudFilesBlobLiveTest.java | 39 ++
.../CloudFilesBlobSignerLiveTest.java | 39 ++
.../CloudFilesContainerIntegrationLiveTest.java | 39 ++
.../CloudFilesContainerLiveTest.java | 56 +++
.../CloudFilesServiceIntegrationLiveTest.java | 39 ++
.../features/CloudFilesAccountApiLiveTest.java | 38 ++
.../v1/features/CloudFilesBulkApiLiveTest.java | 28 ++
.../v1/features/CloudFilesCDNApiLiveTest.java | 105 +++++
.../v1/features/CloudFilesCDNApiMockTest.java | 381 +++++++++++++++++++
.../CloudFilesContainerApiLiveTest.java | 27 ++
.../features/CloudFilesObjectApiLiveTest.java | 27 ++
.../v1/internal/BaseCloudFilesApiLiveTest.java | 37 ++
.../src/test/resources/cdn_container_list.json | 42 ++
.../test/resources/cdn_container_list_at.json | 22 ++
.../src/test/resources/logback.xml | 71 ++++
providers/rackspace-cloudfiles-us/README.md | 20 +
providers/rackspace-cloudfiles-us/pom.xml | 176 +++++++++
.../us/CloudFilesUSProviderMetadata.java | 145 +++++++
.../org.jclouds.providers.ProviderMetadata | 18 +
.../cloudfiles/us/CloudFilesUSProviderTest.java | 29 ++
.../CloudFilesUSBlobIntegrationLiveTest.java | 27 ++
.../integration/CloudFilesUSBlobLiveTest.java | 27 ++
.../CloudFilesUSBlobSignerLiveTest.java | 27 ++
...loudFilesUSContainerIntegrationLiveTest.java | 27 ++
.../CloudFilesUSContainerLiveTest.java | 27 ++
.../CloudFilesUSServiceIntegrationLiveTest.java | 36 ++
.../src/test/resources/logback.xml | 71 ++++
47 files changed, 3296 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds/blob/2ca0dac7/apis/rackspace-cloudfiles/README.md
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudfiles/README.md b/apis/rackspace-cloudfiles/README.md
new file mode 100644
index 0000000..1142323
--- /dev/null
+++ b/apis/rackspace-cloudfiles/README.md
@@ -0,0 +1,20 @@
+Rackspace Cloud Files
+==========================
+
+The new Rackspace Cloud Files multi-region based service API.
+
+This new "rackspace-cloudfiles" API supercedes the jclouds "cloudfiles" API, which will eventually be deprecated.
+
+With this multi-region support, each BlobStore can be isolated to a specific region:
+
+ RegionScopedBlobStoreContext ctx =
+ contextBuilder.buildView(RegionScopedBlobStoreContext.class);
+
+ Set<String> regionIds = ctx.configuredRegions();
+
+ // isolated to a specific region
+ BlobStore dfwBlobStore = ctx.blobStoreInRegion("DFW");
+ BlobStore iadBlobStore = ctx.blobStoreInRegion("IAD");
+
+Production ready?
+No
http://git-wip-us.apache.org/repos/asf/jclouds/blob/2ca0dac7/apis/rackspace-cloudfiles/pom.xml
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudfiles/pom.xml b/apis/rackspace-cloudfiles/pom.xml
new file mode 100644
index 0000000..59662c9
--- /dev/null
+++ b/apis/rackspace-cloudfiles/pom.xml
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF 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.apache.jclouds</groupId>
+ <artifactId>jclouds-project</artifactId>
+ <version>1.8.0-SNAPSHOT</version>
+ </parent>
+
+ <!-- TODO: when out of labs, switch to org.jclouds.api -->
+ <groupId>org.apache.jclouds.labs</groupId>
+ <artifactId>rackspace-cloudfiles</artifactId>
+ <version>1.8.0-SNAPSHOT</version>
+ <name>jclouds rackspace-cloudfiles api</name>
+ <description>jclouds components to access Rackspace Cloud Files</description>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <!-- identity endpoint -->
+ <test.rackspace-cloudfiles.endpoint>https://identity.api.rackspacecloud.com/v2.0/</test.rackspace-cloudfiles.endpoint>
+ <test.rackspace-cloudfiles.api-version>1</test.rackspace-cloudfiles.api-version>
+ <test.rackspace-cloudfiles.build-version />
+ <test.rackspace-cloudfiles.identity>FIXME_IDENTITY</test.rackspace-cloudfiles.identity>
+ <test.rackspace-cloudfiles.credential>FIXME_CREDENTIALS</test.rackspace-cloudfiles.credential>
+ <jclouds.osgi.export>org.jclouds.rackspace.cloudfiles.v1*;version="${project.version}"</jclouds.osgi.export>
+ <jclouds.osgi.import>org.jclouds*;version="${jclouds.version}",*</jclouds.osgi.import>
+ </properties>
+
+ <repositories>
+ <repository>
+ <id>apache-snapshots</id>
+ <url>https://repository.apache.org/content/repositories/snapshots</url>
+ <releases>
+ <enabled>false</enabled>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.jclouds.labs</groupId>
+ <artifactId>openstack-swift</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jclouds.labs</groupId>
+ <artifactId>openstack-swift</artifactId>
+ <version>${project.parent.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jclouds.api</groupId>
+ <artifactId>openstack-keystone</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jclouds.api</groupId>
+ <artifactId>openstack-keystone</artifactId>
+ <version>${project.parent.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jclouds.api</groupId>
+ <artifactId>rackspace-cloudidentity</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jclouds</groupId>
+ <artifactId>jclouds-core</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jclouds</groupId>
+ <artifactId>jclouds-core</artifactId>
+ <version>${project.parent.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jclouds</groupId>
+ <artifactId>jclouds-blobstore</artifactId>
+ <version>${project.parent.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.shrinkwrap</groupId>
+ <artifactId>shrinkwrap-depchain</artifactId>
+ <version>1.2.0</version>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jclouds.driver</groupId>
+ <artifactId>jclouds-slf4j</artifactId>
+ <version>${project.parent.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.squareup.okhttp</groupId>
+ <artifactId>mockwebserver</artifactId>
+ <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>
+ <forkCount>5</forkCount>
+ <reuseForks>true</reuseForks>
+ <parallel>classes</parallel>
+ <systemPropertyVariables>
+ <test.rackspace-cloudfiles.endpoint>${test.rackspace-cloudfiles.endpoint}</test.rackspace-cloudfiles.endpoint>
+ <test.rackspace-cloudfiles.api-version>${test.rackspace-cloudfiles.api-version}</test.rackspace-cloudfiles.api-version>
+ <test.rackspace-cloudfiles.build-version>${test.rackspace-cloudfiles.build-version}</test.rackspace-cloudfiles.build-version>
+ <test.rackspace-cloudfiles.identity>${test.rackspace-cloudfiles.identity}</test.rackspace-cloudfiles.identity>
+ <test.rackspace-cloudfiles.credential>${test.rackspace-cloudfiles.credential}</test.rackspace-cloudfiles.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>
+
+</project>
http://git-wip-us.apache.org/repos/asf/jclouds/blob/2ca0dac7/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/CloudFilesApi.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/CloudFilesApi.java b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/CloudFilesApi.java
new file mode 100644
index 0000000..19667d7
--- /dev/null
+++ b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/CloudFilesApi.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.rackspace.cloudfiles.v1;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.openstack.swift.v1.SwiftApi;
+import org.jclouds.rackspace.cloudfiles.v1.features.CDNApi;
+import org.jclouds.rackspace.cloudfiles.v1.functions.RegionToCDNEndpoint;
+import org.jclouds.rest.annotations.Delegate;
+import org.jclouds.rest.annotations.EndpointParam;
+
+/**
+ * Rackspace Cloud Files is an affordable, redundant, scalable, and dynamic storage service
+ * offering. The core storage system is designed to provide a secure, network-accessible way to
+ * store an unlimited number of files. Each file can be as large as 5 gigabytes.
+ * <p/>
+ * Additionally, Cloud Files provides a simple yet powerful way to publish and distribute content
+ * behind a Content Distribution Network.
+ *
+ * @author Jeremy Daggett
+ *
+ * @see CDNApi
+ * @see SwiftApi
+ */
+public interface CloudFilesApi extends SwiftApi {
+
+ /**
+ * Provides access to Cloud Files CDN features.
+ *
+ * @param region the region to access the CDN API.
+ *
+ * @return the {@link CDNApi} for the specified region.
+ */
+ @Delegate
+ CDNApi cdnApiInRegion(@EndpointParam(parser = RegionToCDNEndpoint.class) @Nullable String region);
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/2ca0dac7/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/CloudFilesApiMetadata.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/CloudFilesApiMetadata.java b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/CloudFilesApiMetadata.java
new file mode 100644
index 0000000..d28b40f
--- /dev/null
+++ b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/CloudFilesApiMetadata.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.rackspace.cloudfiles.v1;
+
+import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE;
+import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;
+import static org.jclouds.reflect.Reflection2.typeToken;
+
+import java.net.URI;
+import java.util.Properties;
+
+import org.jclouds.apis.ApiMetadata;
+import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.RegionModule;
+import org.jclouds.openstack.swift.v1.SwiftApiMetadata;
+import org.jclouds.openstack.swift.v1.blobstore.RegionScopedBlobStoreContext;
+import org.jclouds.openstack.swift.v1.blobstore.config.SignUsingTemporaryUrls;
+import org.jclouds.openstack.swift.v1.blobstore.config.SwiftBlobStoreContextModule;
+import org.jclouds.openstack.swift.v1.config.SwiftTypeAdapters;
+import org.jclouds.openstack.v2_0.ServiceType;
+import org.jclouds.rackspace.cloudfiles.v1.config.CloudFilesHttpApiModule;
+import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationApiModule;
+import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationModule;
+import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityCredentialTypes;
+import org.jclouds.rest.internal.BaseHttpApiMetadata;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+
+/**
+ * Implementation of {@link ApiMetadata} for Cloud Files.
+ *
+ * @author Jeremy Daggett
+ */
+public class CloudFilesApiMetadata extends BaseHttpApiMetadata<CloudFilesApi> {
+
+ @Override
+ public Builder toBuilder() {
+ return new Builder().fromApiMetadata(this);
+ }
+
+ public CloudFilesApiMetadata() {
+ this(new Builder());
+ }
+
+ protected CloudFilesApiMetadata(Builder builder) {
+ super(builder);
+ }
+
+ public static Properties defaultProperties() {
+ Properties properties = SwiftApiMetadata.defaultProperties();
+ properties.setProperty(CREDENTIAL_TYPE, CloudIdentityCredentialTypes.API_KEY_CREDENTIALS);
+ properties.setProperty(SERVICE_TYPE, ServiceType.OBJECT_STORE);
+ return properties;
+ }
+
+ public static class Builder extends BaseHttpApiMetadata.Builder<CloudFilesApi, Builder> {
+
+ protected Builder() {
+ id("rackspace-cloudfiles")
+ .name("Rackspace Cloud Files API")
+ .identityName("${userName}")
+ .credentialName("${apiKey}")
+ .documentation(URI.create("http://docs.rackspace.com/files/api/v1/cf-devguide/content/index.html"))
+ .version("1.0")
+ .endpointName("Rackspace Cloud Identity service URL ending in /v2.0/")
+ .defaultEndpoint("https://identity.api.rackspacecloud.com/v2.0/")
+ .defaultProperties(CloudFilesApiMetadata.defaultProperties())
+ .view(typeToken(RegionScopedBlobStoreContext.class))
+ .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+ .add(CloudIdentityAuthenticationApiModule.class)
+ .add(CloudIdentityAuthenticationModule.class)
+ .add(RegionModule.class)
+ .add(SwiftTypeAdapters.class)
+ .add(CloudFilesHttpApiModule.class)
+ .add(SwiftBlobStoreContextModule.class)
+ .add(SignUsingTemporaryUrls.class)
+ .build());
+ }
+
+ @Override
+ public CloudFilesApiMetadata build() {
+ return new CloudFilesApiMetadata(this);
+ }
+
+ @Override
+ protected Builder self() {
+ return this;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/2ca0dac7/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/binders/BindCDNPurgeEmailAddressesToHeaders.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/binders/BindCDNPurgeEmailAddressesToHeaders.java b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/binders/BindCDNPurgeEmailAddressesToHeaders.java
new file mode 100644
index 0000000..c23f068
--- /dev/null
+++ b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/binders/BindCDNPurgeEmailAddressesToHeaders.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.rackspace.cloudfiles.v1.binders;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.List;
+
+import javax.inject.Singleton;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rackspace.cloudfiles.v1.features.CDNApi;
+import org.jclouds.rackspace.cloudfiles.v1.reference.CloudFilesHeaders;
+import org.jclouds.rest.Binder;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableMultimap;
+
+/**
+ * Binds a list of email addresses to request headers.
+ *
+ * @see {@link CDNApi#purgeObject(String, String, Iterable)}
+ *
+ * @author Jeremy Daggett
+ */
+@Singleton
+public class BindCDNPurgeEmailAddressesToHeaders implements Binder {
+ @SuppressWarnings("unchecked")
+ @Override
+ public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+ checkArgument(checkNotNull(input, "input") instanceof Iterable<?>, "this binder is only valid for Iterable!");
+ checkNotNull(request, "request");
+
+ Iterable<String> emails = (Iterable<String>) input;
+ String emailCSV = Joiner.on(", ").join((List<String>) emails);
+ ImmutableMultimap<String, String> headers =
+ ImmutableMultimap.<String, String> of(CloudFilesHeaders.CDN_PURGE_OBJECT_EMAIL, emailCSV);
+
+ return (R) request.toBuilder().replaceHeaders(headers).build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/2ca0dac7/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/config/CloudFilesHttpApiModule.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/config/CloudFilesHttpApiModule.java b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/config/CloudFilesHttpApiModule.java
new file mode 100644
index 0000000..092fec9
--- /dev/null
+++ b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/config/CloudFilesHttpApiModule.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.rackspace.cloudfiles.v1.config;
+
+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.openstack.swift.v1.SwiftApi;
+import org.jclouds.openstack.swift.v1.config.BaseSwiftHttpApiModule;
+import org.jclouds.rackspace.cloudfiles.v1.CloudFilesApi;
+import org.jclouds.rackspace.cloudfiles.v1.handlers.CloudFilesErrorHandler;
+import org.jclouds.rest.ConfiguresHttpApi;
+
+import com.google.inject.Scopes;
+
+@ConfiguresHttpApi
+public class CloudFilesHttpApiModule extends BaseSwiftHttpApiModule<CloudFilesApi> {
+
+ public CloudFilesHttpApiModule() {
+ super(CloudFilesApi.class);
+ }
+
+ @Override
+ protected void configure() {
+ super.configure();
+ bind(SwiftApi.class).to(CloudFilesApi.class).in(Scopes.SINGLETON);
+ }
+
+ @Override
+ protected void bindErrorHandlers() {
+ bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(CloudFilesErrorHandler.class);
+ bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(CloudFilesErrorHandler.class);
+ bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(CloudFilesErrorHandler.class);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/2ca0dac7/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/domain/CDNContainer.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/domain/CDNContainer.java b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/domain/CDNContainer.java
new file mode 100644
index 0000000..590bccb
--- /dev/null
+++ b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/domain/CDNContainer.java
@@ -0,0 +1,264 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.rackspace.cloudfiles.v1.domain;
+
+import static com.google.common.base.Objects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.net.URI;
+
+import javax.inject.Named;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Represents a CDN Container in Rackspace Cloud Files.
+ *
+ * @author Jeremy Daggett
+ */
+public class CDNContainer implements Comparable<CDNContainer> {
+
+ private String name;
+ @Named("cdn_enabled")
+ private boolean enabled;
+ @Named("log_retention")
+ private boolean logRetention;
+ private int ttl;
+ @Named("cdn_uri")
+ private URI uri;
+ @Named("cdn_ssl_uri")
+ private URI sslUri;
+ @Named("cdn_streaming_uri")
+ private URI streamingUri;
+ @Named("cdn_ios_uri")
+ private URI iosUri;
+
+ @ConstructorProperties({ "name", "cdn_enabled", "log_retention", "ttl", "cdn_uri", "cdn_ssl_uri", "cdn_streaming_uri", "cdn_ios_uri"})
+ public CDNContainer(String name, boolean enabled, boolean logRetention, int ttl, URI uri, URI sslUri, URI streamingUri, URI iosUri) {
+ this.name = checkNotNull(name, "name required");
+ this.enabled = enabled;
+ this.logRetention = logRetention;
+ this.ttl = ttl;
+ this.uri = checkNotNull(uri, "uri required");
+ this.sslUri = checkNotNull(sslUri, "sslUri required");
+ this.streamingUri = checkNotNull(streamingUri, "streamingUri required");
+ this.iosUri = checkNotNull(iosUri, "iosUri required");
+ }
+
+ /**
+ * <h3>NOTE</h3>
+ * The container name is not available from HEAD CDN responses and will be null.
+ *
+ * @return The name of this CDN container.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @return {@code true} if the container is CDN enabled, {@code false} if not.
+ */
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ /**
+ * @return {@code true} if the logs will be retained for this CDN container, {@code false} if not.
+ */
+ public boolean isLogRetentionEnabled() {
+ return logRetention;
+ }
+
+ /**
+ * @return the TTL for this CDN container.
+ */
+ public int getTtl() {
+ return ttl;
+ }
+
+ /**
+ * @return the {@link URI} for this CDN container.
+ */
+ public URI getUri() {
+ return uri;
+ }
+
+ /**
+ * @return the SSL {@link URI} for this CDN container.
+ */
+ public URI getSslUri() {
+ return sslUri;
+ }
+
+ /**
+ * @return the streaming {@link URI} for this CDN container.
+ */
+ public URI getStreamingUri() {
+ return streamingUri;
+ }
+
+ /**
+ * @return the iOS {@link URI} for this CDN container.
+ */
+ public URI getIosUri() {
+ return iosUri;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null || getClass() != obj.getClass()) return false;
+ CDNContainer that = CDNContainer.class.cast(obj);
+ return Objects.equal(this.name, that.name)
+ && Objects.equal(this.enabled, that.enabled)
+ && Objects.equal(this.logRetention, that.logRetention)
+ && Objects.equal(this.ttl, that.ttl)
+ && Objects.equal(this.uri, that.uri)
+ && Objects.equal(this.sslUri, that.sslUri)
+ && Objects.equal(this.streamingUri, that.streamingUri)
+ && Objects.equal(this.iosUri, that.iosUri);
+ }
+
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(getName(), isEnabled(), isLogRetentionEnabled(), getTtl(), getUri(), getSslUri(), getStreamingUri(), getIosUri());
+ }
+
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ protected ToStringHelper string() {
+ return toStringHelper("").omitNullValues()
+ .add("name", getName())
+ .add("enabled", isEnabled())
+ .add("logRetention", isLogRetentionEnabled())
+ .add("ttl", getTtl())
+ .add("uri", getUri())
+ .add("sslUri", getSslUri())
+ .add("streamingUri", getStreamingUri())
+ .add("iosUri", getIosUri());
+ }
+
+ @Override
+ public int compareTo(CDNContainer that) {
+ if (that == null)
+ return 1;
+ if (this == that)
+ return 0;
+ return this.getName().compareTo(that.getName());
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+
+ private String name;
+ private boolean enabled;
+ private boolean logRetention;
+ private int ttl;
+ private URI uri;
+ private URI sslUri;
+ private URI streamingUri;
+ private URI iosUri;
+
+ /**
+ * @see CDNContainer#getName()
+ */
+ public Builder name(String name) {
+ this.name = checkNotNull(name, "name");
+ return this;
+ }
+
+ /**
+ * @see CDNContainer#isEnabled()
+ */
+ public Builder enabled(boolean enabled) {
+ this.enabled = enabled;
+ return this;
+ }
+
+ /**
+ * @see CDNContainer#isLogRetentionEnabled()
+ */
+ public Builder logRetention(boolean logRetention) {
+ this.logRetention = logRetention;
+ return this;
+ }
+
+ /**
+ * @see CDNContainer#getTtl()
+ */
+ public Builder ttl(int ttl) {
+ this.ttl = ttl;
+ return this;
+ }
+
+ /**
+ * @see CDNContainer#getUri()
+ */
+ public Builder uri(URI uri) {
+ this.uri = uri;
+ return this;
+ }
+
+ /**
+ * @see CDNContainer#getSslUri()
+ */
+ public Builder sslUri(URI sslUri) {
+ this.sslUri = sslUri;
+ return this;
+ }
+
+ /**
+ * @see CDNContainer#getStreamingUri()
+ */
+ public Builder streamingUri(URI streamingUri) {
+ this.streamingUri = streamingUri;
+ return this;
+ }
+
+ /**
+ * @see CDNContainer#getIosUri()
+ */
+ public Builder iosUri(URI iosUri) {
+ this.iosUri = iosUri;
+ return this;
+ }
+
+ public CDNContainer build() {
+ return new CDNContainer(name, enabled, logRetention, ttl, uri, sslUri, streamingUri, iosUri);
+ }
+
+ public Builder fromContainer(CDNContainer from) {
+ return name(from.getName())
+ .enabled(from.isEnabled())
+ .logRetention(from.isLogRetentionEnabled())
+ .ttl(from.getTtl())
+ .uri(from.getUri())
+ .sslUri(from.getSslUri())
+ .streamingUri(from.getStreamingUri())
+ .iosUri(from.getIosUri());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/2ca0dac7/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/features/CDNApi.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/features/CDNApi.java b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/features/CDNApi.java
new file mode 100644
index 0000000..326b951
--- /dev/null
+++ b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/features/CDNApi.java
@@ -0,0 +1,205 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.rackspace.cloudfiles.v1.features;
+
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+import static org.jclouds.rackspace.cloudfiles.v1.reference.CloudFilesHeaders.CDN_ENABLED;
+import static org.jclouds.rackspace.cloudfiles.v1.reference.CloudFilesHeaders.CDN_TTL;
+
+import java.io.Closeable;
+import java.net.URI;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.HEAD;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+
+import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
+import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
+import org.jclouds.openstack.swift.v1.options.ListContainerOptions;
+import org.jclouds.rackspace.cloudfiles.v1.CloudFilesApi;
+import org.jclouds.rackspace.cloudfiles.v1.binders.BindCDNPurgeEmailAddressesToHeaders;
+import org.jclouds.rackspace.cloudfiles.v1.domain.CDNContainer;
+import org.jclouds.rackspace.cloudfiles.v1.functions.ParseCDNContainerFromHeaders;
+import org.jclouds.rackspace.cloudfiles.v1.functions.ParseCDNContainerURIFromHeaders;
+import org.jclouds.rackspace.cloudfiles.v1.options.UpdateCDNContainerOptions;
+import org.jclouds.rackspace.cloudfiles.v1.reference.CloudFilesHeaders;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.Headers;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+
+import com.google.common.collect.FluentIterable;
+/**
+ * Provides access to the Rackspace Cloud Files CDN API features.
+ *
+ * <h3>NOTE</h3>
+ * Before a container can be CDN enabled, it must exist in the storage system.
+ * To CDN enable the container, perform PUT request against it using the <code>publicURL</code>
+ * noted in the service catalog for Cloud Files during Authentication and set the
+ * <code>X-CDN-Enabled</code> header to <code>true</code>.
+ *
+ * @author Jeremy Daggett
+ *
+ * @see {@link CloudFilesApi#cdnApiInRegion(String)}
+ */
+@RequestFilters(AuthenticateRequest.class)
+@Consumes(APPLICATION_JSON)
+public interface CDNApi extends Closeable {
+
+ /**
+ * Lists up to 10,000 CDN containers.
+ *
+ * @return a list of CDN enabled containers ordered by name.
+ */
+ @Named("cdn:list")
+ @GET
+ @QueryParams(keys = {"format", "enabled_only"}, values = {"json", "true"})
+ @Fallback(EmptyFluentIterableOnNotFoundOr404.class)
+ @Path("/")
+ FluentIterable<CDNContainer> list();
+
+ /**
+ * Lists CDN containers, with the given options.
+ *
+ * @param options
+ * the options to control output.
+ *
+ * @return a list of CDN enabled containers ordered by name.
+ */
+ @Named("cdn:list")
+ @GET
+ @QueryParams(keys = {"format", "enabled_only"}, values = {"json", "true"})
+ @Fallback(EmptyFluentIterableOnNotFoundOr404.class)
+ @Path("/")
+ FluentIterable<CDNContainer> list(ListContainerOptions options);
+
+ /**
+ * Gets the specified CDN Container.
+ *
+ * @param containerName
+ * the name of the CDN Container
+ *
+ * @return the CDNContainer or null, if not found.
+ */
+ @Named("cdn:get")
+ @HEAD
+ @ResponseParser(ParseCDNContainerFromHeaders.class)
+ @Fallback(NullOnNotFoundOr404.class)
+ @Path("/{container}")
+ @Nullable
+ CDNContainer get(@PathParam("container") String containerName);
+
+ /**
+ * Enables the {@link CDNContainer}.
+ *
+ * @param containerName
+ * corresponds to {@link CDNContainer#getName()}.
+ *
+ * @return the CDN container {@link URI} or {@code null}, if not found.
+ */
+ @Named("cdn:enable")
+ @PUT
+ @ResponseParser(ParseCDNContainerURIFromHeaders.class)
+ @Fallback(NullOnNotFoundOr404.class)
+ @Path("/{containerName}")
+ @Headers(keys = CDN_ENABLED, values = "true")
+ @Nullable
+ URI enable(@PathParam("containerName") String containerName);
+
+ /**
+ * Enables the {@link CDNContainer} with a TTL.
+ *
+ * @param containerName
+ * corresponds to {@link CDNContainer#name()}.
+ * @param ttl
+ * the TTL for the CDN Container.
+ *
+ * @return the CDN container {@link URI} or {@code null}, if not found.
+ */
+ @Named("cdn:enable")
+ @PUT
+ @ResponseParser(ParseCDNContainerURIFromHeaders.class)
+ @Fallback(NullOnNotFoundOr404.class)
+ @Path("/{containerName}")
+ @Headers(keys = CDN_ENABLED, values = "true")
+ @Nullable
+ URI enable(@PathParam("containerName") String containerName,
+ @HeaderParam(CDN_TTL) int ttl);
+
+ /**
+ * Disables the {@link CDNContainer}.
+ *
+ * @param containerName
+ * corresponds to {@link CDNContainer#name()}.
+ *
+ * @return {@code true} if the container was disabled, {@code false} if not.
+ */
+ @Named("cdn:disable")
+ @PUT
+ @Fallback(FalseOnNotFoundOr404.class)
+ @Path("/{containerName}")
+ @Headers(keys = CDN_ENABLED, values = "False")
+ boolean disable(@PathParam("containerName") String containerName);
+
+ /**
+ * Purges an object from the CDN.
+ *
+ * @param containerName
+ * corresponds to {@link CDNContainer#name()}.
+ * @param objectName
+ * the object in the {@link CDNContainer} to purge.
+ * @param emails
+ * the email addresses to notify after purging.
+ *
+ * @return {@code true} if the object was successfully purged, {@code false} if not.
+ */
+ @Named("cdn:purge")
+ @DELETE
+ @Fallback(FalseOnNotFoundOr404.class)
+ @Path("/{containerName}/{objectName}")
+ @Headers(keys = CloudFilesHeaders.CDN_PURGE_OBJECT_EMAIL, values = "{email}")
+ boolean purgeObject(@PathParam("containerName") String containerName,
+ @PathParam("objectName") String objectName,
+ @BinderParam(BindCDNPurgeEmailAddressesToHeaders.class) Iterable<String> emails);
+
+ /**
+ * Updates a CDN container with the supplied {@link UpdateCDNContainerOptions} options.
+ *
+ * @param containerName
+ * corresponds to {@link CDNContainer#name()}.
+ *
+ * @param options
+ * the {@link UpdateCDNContainerOptions} options.
+ */
+ @Named("cdn:update")
+ @POST
+ @Fallback(FalseOnNotFoundOr404.class)
+ @Path("/{containerName}")
+ boolean update(@PathParam("containerName") String containerName, UpdateCDNContainerOptions options);
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/2ca0dac7/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/functions/ParseCDNContainerFromHeaders.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/functions/ParseCDNContainerFromHeaders.java b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/functions/ParseCDNContainerFromHeaders.java
new file mode 100644
index 0000000..e551ab1
--- /dev/null
+++ b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/functions/ParseCDNContainerFromHeaders.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.rackspace.cloudfiles.v1.functions;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Lists.newArrayList;
+import static org.jclouds.rackspace.cloudfiles.v1.reference.CloudFilesHeaders.CDN_ENABLED;
+import static org.jclouds.rackspace.cloudfiles.v1.reference.CloudFilesHeaders.CDN_IOS_URI;
+import static org.jclouds.rackspace.cloudfiles.v1.reference.CloudFilesHeaders.CDN_LOG_RETENTION;
+import static org.jclouds.rackspace.cloudfiles.v1.reference.CloudFilesHeaders.CDN_SSL_URI;
+import static org.jclouds.rackspace.cloudfiles.v1.reference.CloudFilesHeaders.CDN_STREAMING_URI;
+import static org.jclouds.rackspace.cloudfiles.v1.reference.CloudFilesHeaders.CDN_TTL;
+import static org.jclouds.rackspace.cloudfiles.v1.reference.CloudFilesHeaders.CDN_URI;
+
+import java.net.URI;
+import java.util.List;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.rackspace.cloudfiles.v1.domain.CDNContainer;
+import org.jclouds.rest.InvocationContext;
+
+import com.google.common.base.Function;
+import com.google.common.base.Splitter;
+
+/**
+ * Parses the {@link CDNContainer} from the response headers.
+ *
+ * @author Jeremy Daggett
+ *
+ */
+public class ParseCDNContainerFromHeaders implements Function<HttpResponse, CDNContainer>,
+ InvocationContext<ParseCDNContainerFromHeaders> {
+
+ private HttpRequest request;
+
+ /**
+ * parses the http response headers to create a new {@link CDNContainer} object.
+ */
+ public CDNContainer apply(final HttpResponse from) {
+ String uri = checkNotNull(from.getFirstHeaderOrNull(CDN_URI), CDN_URI);
+ String sslUri = checkNotNull(from.getFirstHeaderOrNull(CDN_SSL_URI), CDN_SSL_URI);
+ String streamingUri = checkNotNull(from.getFirstHeaderOrNull(CDN_STREAMING_URI), CDN_STREAMING_URI);
+ String iosUri = checkNotNull(from.getFirstHeaderOrNull(CDN_IOS_URI), CDN_IOS_URI);
+ String enabled = checkNotNull(from.getFirstHeaderOrNull(CDN_ENABLED), CDN_ENABLED);
+ String logRetention = checkNotNull(from.getFirstHeaderOrNull(CDN_LOG_RETENTION), CDN_LOG_RETENTION);
+ String ttl = checkNotNull(from.getFirstHeaderOrNull(CDN_TTL), CDN_TTL);
+
+ // just need the name from the path
+ List<String> parts = newArrayList(Splitter.on('/').split(request.getEndpoint().getPath()));
+ checkArgument(parts.size() > 0);
+
+ return CDNContainer.builder().name(parts.get(parts.size() - 1))
+ .enabled(Boolean.parseBoolean(enabled))
+ .logRetention(Boolean.parseBoolean(logRetention))
+ .ttl(Integer.parseInt(ttl))
+ .uri(URI.create(uri))
+ .sslUri(URI.create(sslUri))
+ .streamingUri(URI.create(streamingUri))
+ .iosUri(URI.create(iosUri))
+ .build();
+ }
+
+ @Override
+ public ParseCDNContainerFromHeaders setContext(HttpRequest request) {
+ this.request = request;
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/2ca0dac7/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/functions/ParseCDNContainerURIFromHeaders.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/functions/ParseCDNContainerURIFromHeaders.java b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/functions/ParseCDNContainerURIFromHeaders.java
new file mode 100644
index 0000000..4a29f60
--- /dev/null
+++ b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/functions/ParseCDNContainerURIFromHeaders.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.rackspace.cloudfiles.v1.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.URI;
+
+import org.jclouds.http.HttpResponse;
+import org.jclouds.rackspace.cloudfiles.v1.domain.CDNContainer;
+import org.jclouds.rackspace.cloudfiles.v1.reference.CloudFilesHeaders;
+
+import com.google.common.base.Function;
+
+/**
+ * Parses the {@link CDNContainer} from the response headers.
+ *
+ * @author Jeremy Daggett
+ *
+ */
+public class ParseCDNContainerURIFromHeaders implements Function<HttpResponse, URI> {
+
+ /**
+ * parses the http response headers to provide the CDN URI string.
+ */
+ public URI apply(final HttpResponse from) {
+ String cdnUri = checkNotNull(from.getFirstHeaderOrNull(CloudFilesHeaders.CDN_URI),
+ CloudFilesHeaders.CDN_URI);
+ return URI.create(cdnUri);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/2ca0dac7/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/functions/RegionToCDNEndpoint.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/functions/RegionToCDNEndpoint.java b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/functions/RegionToCDNEndpoint.java
new file mode 100644
index 0000000..3b5361a
--- /dev/null
+++ b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/functions/RegionToCDNEndpoint.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.rackspace.cloudfiles.v1.functions;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.net.URI;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.functions.RegionToEndpoint;
+import org.jclouds.location.suppliers.RegionIdToURISupplier;
+import org.jclouds.rackspace.cloudfiles.v1.CloudFilesApi;
+import org.jclouds.rackspace.cloudfiles.v1.features.CDNApi;
+import org.jclouds.rackspace.cloudidentity.v2_0.ServiceType;
+import org.jclouds.rest.annotations.ApiVersion;
+
+import com.google.common.base.Function;
+import com.google.common.base.Supplier;
+
+/**
+ * This class ensures that the correct Cloud Files CDN endpoint is retrieved from the endpoint
+ * supplier. The CDN API should never be instantiated directly, but rather accessed through the
+ * {@link CloudFilesApi#cdnApiInRegion(String)} API.
+ * <p/>
+ * <h3>NOTE</h3>
+ * The Cloud Files Service Type will always default to OpenStack Object Storage ("object-storage").
+ * <p/>
+ *
+ * @author Jeremy Daggett
+ *
+ * @see CloudFilesApi#cdnApiInRegion(String)
+ * @see CDNApi
+ * @see RegionToEndpoint
+ * @see org.jclouds.openstack.v2_0.ServiceType#OBJECT_STORE
+ * @see org.jclouds.rackspace.cloudidentity.v2_0.ServiceType#OBJECT_CDN
+ * @see <a
+ * href="http://docs.rackspace.com/files/api/v1/cf-devguide/content/Service-Access-Endpoints-d1e003.html">
+ * Service Access Endpoints</a>
+ */
+@Singleton
+public class RegionToCDNEndpoint implements Function<Object, URI> {
+
+ private final Supplier<Map<String, Supplier<URI>>> endpointsSupplier;
+
+ @Inject
+ public RegionToCDNEndpoint(@ApiVersion final String apiVersion, final RegionIdToURISupplier.Factory factory) {
+ this.endpointsSupplier = factory.createForApiTypeAndVersion(ServiceType.OBJECT_CDN, apiVersion);
+ }
+
+ public URI apply(@Nullable Object from) {
+ checkArgument(from != null && from instanceof String, "you must specify a region, as a String argument");
+ Map<String, Supplier<URI>> regionToEndpoint = endpointsSupplier.get();
+ checkState(regionToEndpoint.size() > 0, "no region name to endpoint mappings configured!");
+ checkArgument(regionToEndpoint.containsKey(from),
+ "requested location %s, which is not in the configured locations: %s", from, regionToEndpoint);
+ return regionToEndpoint.get(from).get();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/2ca0dac7/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/handlers/CloudFilesErrorHandler.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/handlers/CloudFilesErrorHandler.java b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/handlers/CloudFilesErrorHandler.java
new file mode 100644
index 0000000..1e69b23
--- /dev/null
+++ b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/handlers/CloudFilesErrorHandler.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.rackspace.cloudfiles.v1.handlers;
+
+import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+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.openstack.swift.v1.CopyObjectException;
+import org.jclouds.openstack.swift.v1.reference.SwiftHeaders;
+import org.jclouds.rest.AuthorizationException;
+import org.jclouds.rest.InsufficientResourcesException;
+
+// TODO: is there error spec someplace? let's type errors, etc.
+public class CloudFilesErrorHandler 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:
+ Exception oldException = exception;
+ String sourcePath = command.getCurrentRequest().getFirstHeaderOrNull(SwiftHeaders.OBJECT_COPY_FROM);
+ if (sourcePath != null) {
+ // the path returned here is in the form "/v1/tenant-id/destContainer/destObject"
+ String path = command.getCurrentRequest().getEndpoint().getPath();
+ int startOfDestinationPath = path.lastIndexOf("/", path.lastIndexOf("/") - 1);
+ // get the "/destContainer/destObject" portion of the path
+ String destinationPath = path.substring(startOfDestinationPath);
+
+ exception = new CopyObjectException(sourcePath, destinationPath, message);
+ exception.initCause(oldException);
+ } else if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
+ String path = command.getCurrentRequest().getEndpoint().getPath();
+ Matcher matcher = CONTAINER_PATH.matcher(path);
+
+ 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;
+ case 409:
+ exception = new IllegalStateException(exception.getMessage(), exception);
+ break;
+ case 413:
+ exception = new InsufficientResourcesException(exception.getMessage(), exception);
+ break;
+ }
+ command.setException(exception);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/2ca0dac7/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/options/UpdateCDNContainerOptions.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/options/UpdateCDNContainerOptions.java b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/options/UpdateCDNContainerOptions.java
new file mode 100644
index 0000000..d044657
--- /dev/null
+++ b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/options/UpdateCDNContainerOptions.java
@@ -0,0 +1,163 @@
+/*
+
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.rackspace.cloudfiles.v1.options;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static org.jclouds.rackspace.cloudfiles.v1.reference.CloudFilesHeaders.CDN_ENABLED;
+import static org.jclouds.rackspace.cloudfiles.v1.reference.CloudFilesHeaders.CDN_LOG_RETENTION;
+import static org.jclouds.rackspace.cloudfiles.v1.reference.CloudFilesHeaders.CDN_TTL;
+import static org.jclouds.rackspace.cloudfiles.v1.reference.CloudFilesHeaders.CDN_TTL_MAX;
+import static org.jclouds.rackspace.cloudfiles.v1.reference.CloudFilesHeaders.CDN_TTL_MIN;
+
+import org.jclouds.http.options.BaseHttpRequestOptions;
+
+/**
+ * Contains options supported in the REST API for updating CDN containers.
+ *
+ * <a href=
+ * "http://docs.rackspace.com/files/api/v1/cf-devguide/content/Update_CDN-Enabled_Container_Metadata-d1e2787.html">
+ * Update CDN container</a>.
+ *
+ * @author Jeremy Daggett
+ */
+public class UpdateCDNContainerOptions extends BaseHttpRequestOptions {
+ public static final UpdateCDNContainerOptions NONE = new UpdateCDNContainerOptions();
+
+ /**
+ * Updates TTL
+ */
+ public UpdateCDNContainerOptions ttl(int ttl) {
+ checkState(ttl >= Integer.valueOf(CDN_TTL_MIN), "ttl must be >= " + CDN_TTL_MIN);
+ checkState(ttl <= Integer.valueOf(CDN_TTL_MAX), "ttl must be <= " + CDN_TTL_MAX);
+ headers.put(CDN_TTL, Integer.toString(ttl));
+ return this;
+ }
+
+ /**
+ * Enables or disables log retention
+ */
+ public UpdateCDNContainerOptions logRetention(boolean logRetention) {
+ headers.put(CDN_LOG_RETENTION, Boolean.toString(logRetention));
+ return this;
+ }
+
+ /**
+ * Enables or disables the CDN Container
+ * API to enable disable - is this necessary?
+ */
+ public UpdateCDNContainerOptions enabled(boolean enabled) {
+ headers.put(CDN_ENABLED, Boolean.toString(enabled));
+ return this;
+ }
+
+ /**
+ * Sets the index page for the Static Website.
+ */
+ public UpdateCDNContainerOptions staticWebsiteIndexPage(String indexPage) {
+ checkNotNull(indexPage, "index page cannot be null");
+ headers.put("indexPage", indexPage);
+ return this;
+ }
+
+ /**
+ * Sets the error page for the Static Website.
+ */
+ public UpdateCDNContainerOptions staticWebsiteErrorPage(String errorPage) {
+ checkNotNull(errorPage, "error page cannot be null");
+ headers.put("errorPage", errorPage);
+ return this;
+ }
+
+ /**
+ * Enables or disables listings for the Static Website.
+ */
+ public UpdateCDNContainerOptions staticWebsiteListings(boolean listings) {
+ headers.put("enableListings", Boolean.toString(listings));
+ return this;
+ }
+
+ /**
+ * Sets the CSS pages for the Static Website.
+ */
+ public UpdateCDNContainerOptions staticWebsiteListingsCSS(String listingsCSS) {
+ checkNotNull(listingsCSS, "listingsCSS page cannot be null");
+ headers.put("limit", listingsCSS);
+ return this;
+ }
+
+ public static class Builder {
+ /** @see UpdateCDNContainerOptions#ttl */
+ public static UpdateCDNContainerOptions ttl(int ttl) {
+ UpdateCDNContainerOptions options = new UpdateCDNContainerOptions();
+ return options.ttl(ttl);
+ }
+
+ /**
+ * @see UpdateCDNContainerOptions#logRetention
+ */
+ public static UpdateCDNContainerOptions logRetention(boolean logRetention) {
+ UpdateCDNContainerOptions options = new UpdateCDNContainerOptions();
+ return options.logRetention(logRetention);
+ }
+
+ /**
+ * @see UpdateCDNContainerOptions#enabled
+ */
+ public static UpdateCDNContainerOptions enabled(boolean enabled) {
+ UpdateCDNContainerOptions options = new UpdateCDNContainerOptions();
+ return options.enabled(enabled);
+ }
+
+ /**
+ * @see UpdateCDNContainerOptions#staticWebsiteIndexPage
+ */
+ public static UpdateCDNContainerOptions staticWebsiteIndexPage(String indexPage) {
+ UpdateCDNContainerOptions options = new UpdateCDNContainerOptions();
+ return options.staticWebsiteIndexPage(indexPage);
+ }
+
+ /**
+ * @see UpdateCDNContainerOptions#staticWebsiteErrorPage
+ */
+ public static UpdateCDNContainerOptions staticWebsiteErrorPage(String errorPage) {
+ UpdateCDNContainerOptions options = new UpdateCDNContainerOptions();
+ return options.staticWebsiteErrorPage(errorPage);
+ }
+
+ /**
+ * @see UpdateCDNContainerOptions#staticWebsiteListings
+ */
+ public static UpdateCDNContainerOptions staticWebsiteListings(boolean enabled) {
+ UpdateCDNContainerOptions options = new UpdateCDNContainerOptions();
+ return options.staticWebsiteListings(enabled);
+ }
+
+ /**
+ * @see UpdateCDNContainerOptions#staticWebsiteListingsCSS
+ */
+ public static UpdateCDNContainerOptions staticWebsiteListingsCSS(String cssPage) {
+ UpdateCDNContainerOptions options = new UpdateCDNContainerOptions();
+ return options.staticWebsiteListingsCSS(cssPage);
+ }
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/2ca0dac7/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/reference/CloudFilesHeaders.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/reference/CloudFilesHeaders.java b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/reference/CloudFilesHeaders.java
new file mode 100644
index 0000000..7247700
--- /dev/null
+++ b/apis/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/reference/CloudFilesHeaders.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.rackspace.cloudfiles.v1.reference;
+
+import org.jclouds.openstack.swift.v1.reference.SwiftHeaders;
+
+/**
+ * Additional headers specified by Rackspace Cloud Files CDN.
+ *
+ * @see <a
+ * href="http://docs.rackspace.com/files/api/v1/cf-devguide/content/index.html">
+ * Cloud Files API</a>
+ *
+ * @author Jeremy Daggett
+ */
+public interface CloudFilesHeaders extends SwiftHeaders {
+ // Access logs
+ String CONTAINER_ACCESS_LOG_DELIVERY = CONTAINER_METADATA_PREFIX + "Access-Log-Delivery";
+
+ // Common CDN Headers
+ String CDN_ENABLED = "X-Cdn-Enabled";
+ String CDN_LOG_RETENTION = "X-Log-Retention";
+ String CDN_TTL = "X-Ttl";
+ String CDN_URI = "X-Cdn-Uri";
+ String CDN_SSL_URI = "X-Cdn-Ssl-Uri";
+ String CDN_STREAMING_URI = "X-Cdn-Streaming-Uri";
+ String CDN_IOS_URI = "X-Cdn-Ios-Uri";
+
+ // CDN TTL Limits
+ int CDN_TTL_MIN = 900;
+ int CDN_TTL_MAX = 31536000;
+ int CDN_TTL_DEFAULT = 259200;
+
+ // CDN Purge
+ String CDN_PURGE_OBJECT_EMAIL = "X-Purge-Email";
+ String CDN_PURGE_OBJECT_FAILED = "X-Purge-Failed-Reason";
+
+ // CDN Static Web
+ String STATIC_WEB_INDEX = CONTAINER_METADATA_PREFIX + "Web-Index";
+ String STATIC_WEB_DIRECTORY_TYPE = CONTAINER_METADATA_PREFIX + "Web-Directory-Type";
+ String STATIC_WEB_ERROR = CONTAINER_METADATA_PREFIX + "Web-Error";
+ String STATIC_WEB_LISTINGS = CONTAINER_METADATA_PREFIX + "Web-Listings";
+ String STATIC_WEB_LISTINGS_CSS = CONTAINER_METADATA_PREFIX + "Web-Listings-CSS";
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/2ca0dac7/apis/rackspace-cloudfiles/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudfiles/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata b/apis/rackspace-cloudfiles/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata
new file mode 100644
index 0000000..9be2b32
--- /dev/null
+++ b/apis/rackspace-cloudfiles/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata
@@ -0,0 +1,18 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF 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.
+#
+
+org.jclouds.rackspace.cloudfiles.v1.CloudFilesApiMetadata
http://git-wip-us.apache.org/repos/asf/jclouds/blob/2ca0dac7/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/CloudFilesApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/CloudFilesApiLiveTest.java b/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/CloudFilesApiLiveTest.java
new file mode 100644
index 0000000..666059f
--- /dev/null
+++ b/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/CloudFilesApiLiveTest.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.rackspace.cloudfiles.v1;
+
+import org.jclouds.rackspace.cloudfiles.v1.internal.BaseCloudFilesApiLiveTest;
+import org.testng.annotations.Test;
+
+/**
+ * Tests behavior of {@code CloudFilesApi}
+ *
+ * @author Jeremy Daggett
+ */
+@Test(groups = "live", testName = "CloudFilesApiLiveTest")
+public class CloudFilesApiLiveTest extends BaseCloudFilesApiLiveTest {
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds/blob/2ca0dac7/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/CloudFilesApiMetadataTest.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/CloudFilesApiMetadataTest.java b/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/CloudFilesApiMetadataTest.java
new file mode 100644
index 0000000..5c32f1c
--- /dev/null
+++ b/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/CloudFilesApiMetadataTest.java
@@ -0,0 +1,35 @@
+package org.jclouds.rackspace.cloudfiles.v1;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.
+ */
+
+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 Jeremy Daggett
+ */
+@Test(groups = "unit", testName = "CloudFilesApiMetadataTest")
+public class CloudFilesApiMetadataTest extends BaseApiMetadataTest {
+ public CloudFilesApiMetadataTest() {
+ super(new CloudFilesApiMetadata(), ImmutableSet.<TypeToken<? extends View>> of());
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/2ca0dac7/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/binders/BindCDNPurgeEmailAddressesToHeadersMockTest.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/binders/BindCDNPurgeEmailAddressesToHeadersMockTest.java b/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/binders/BindCDNPurgeEmailAddressesToHeadersMockTest.java
new file mode 100644
index 0000000..5c7e2b0
--- /dev/null
+++ b/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/binders/BindCDNPurgeEmailAddressesToHeadersMockTest.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.rackspace.cloudfiles.v1.binders;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.List;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.openstack.v2_0.internal.BaseOpenStackMockTest;
+import org.jclouds.rackspace.cloudfiles.v1.CloudFilesApi;
+import org.jclouds.rackspace.cloudfiles.v1.reference.CloudFilesHeaders;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Tests behavior of {@code BindCDNPurgeEmailAddressesToHeaders}
+ *
+ * @author Jeremy Daggett
+ */
+@Test(groups = "unit", testName = "BindCDNPurgeEmailAddressesToHeadersMockTest")
+public class BindCDNPurgeEmailAddressesToHeadersMockTest extends BaseOpenStackMockTest<CloudFilesApi> {
+
+ BindCDNPurgeEmailAddressesToHeaders binder = new BindCDNPurgeEmailAddressesToHeaders();
+
+ public void testEmailBind() throws Exception {
+ List<String> emails = ImmutableList.of("foo@bar.com", "bar@foo.com");
+
+ HttpRequest request = purgeRequest();
+
+ HttpRequest actualRequest = binder.bindToRequest(request, emails);
+
+ HttpRequest expectedRequest = HttpRequest.builder()
+ .method("DELETE")
+ .endpoint("https://storage101.dfw1.clouddrive.com/v1/MossoCloudFS_XXXXXX/")
+ .addHeader(CloudFilesHeaders.CDN_PURGE_OBJECT_EMAIL, "foo@bar.com, bar@foo.com")
+ .build();
+
+ assertEquals(actualRequest, expectedRequest);
+
+ }
+
+ @Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "input")
+ public void testNullList() {
+ HttpRequest request = purgeRequest();
+ binder.bindToRequest(request, null);
+ }
+
+ @Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "request")
+ public void testNullRequest() {
+ List<String> emails = ImmutableList.of("foo@bar.com", "bar@foo.com");
+ binder.bindToRequest(null, emails);
+ }
+
+ private static final HttpRequest purgeRequest() {
+ return HttpRequest.builder()
+ .method("DELETE")
+ .endpoint("https://storage101.dfw1.clouddrive.com/v1/MossoCloudFS_XXXXXX/")
+ .build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/2ca0dac7/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/blobstore/CloudFilesRegionScopedBlobStoreContextLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/blobstore/CloudFilesRegionScopedBlobStoreContextLiveTest.java b/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/blobstore/CloudFilesRegionScopedBlobStoreContextLiveTest.java
new file mode 100644
index 0000000..bc35b3a
--- /dev/null
+++ b/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/blobstore/CloudFilesRegionScopedBlobStoreContextLiveTest.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.rackspace.cloudfiles.v1.blobstore;
+
+import static org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityCredentialTypes.API_KEY_CREDENTIALS;
+
+import java.util.Properties;
+
+import org.jclouds.openstack.swift.v1.blobstore.RegionScopedBlobStoreContextLiveTest;
+import org.testng.annotations.Test;
+
+@Test(groups = "live")
+public class CloudFilesRegionScopedBlobStoreContextLiveTest extends RegionScopedBlobStoreContextLiveTest {
+
+ public CloudFilesRegionScopedBlobStoreContextLiveTest() {
+ provider = "rackspace-cloudfiles";
+ }
+
+ @Override
+ protected Properties setupProperties() {
+ Properties props = super.setupProperties();
+ setIfTestSystemPropertyPresent(props, API_KEY_CREDENTIALS);
+ return props;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/2ca0dac7/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/blobstore/integration/CloudFilesBlobIntegrationLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/blobstore/integration/CloudFilesBlobIntegrationLiveTest.java b/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/blobstore/integration/CloudFilesBlobIntegrationLiveTest.java
new file mode 100644
index 0000000..58ed73b
--- /dev/null
+++ b/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/blobstore/integration/CloudFilesBlobIntegrationLiveTest.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.rackspace.cloudfiles.v1.blobstore.integration;
+
+import static org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityCredentialTypes.API_KEY_CREDENTIALS;
+
+import java.util.Properties;
+
+import org.jclouds.openstack.swift.v1.blobstore.integration.SwiftBlobIntegrationLiveTest;
+import org.testng.annotations.Test;
+
+@Test(groups = "live", testName = "CloudFilesBlobIntegrationLiveTest")
+public class CloudFilesBlobIntegrationLiveTest extends SwiftBlobIntegrationLiveTest {
+
+ public CloudFilesBlobIntegrationLiveTest() {
+ provider = "rackspace-cloudfiles";
+ }
+
+ @Override
+ protected Properties setupProperties() {
+ Properties props = super.setupProperties();
+ setIfTestSystemPropertyPresent(props, API_KEY_CREDENTIALS);
+ return props;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/2ca0dac7/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/blobstore/integration/CloudFilesBlobLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/blobstore/integration/CloudFilesBlobLiveTest.java b/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/blobstore/integration/CloudFilesBlobLiveTest.java
new file mode 100644
index 0000000..87519d5
--- /dev/null
+++ b/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/blobstore/integration/CloudFilesBlobLiveTest.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.rackspace.cloudfiles.v1.blobstore.integration;
+
+import static org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityCredentialTypes.API_KEY_CREDENTIALS;
+
+import java.util.Properties;
+
+import org.jclouds.openstack.swift.v1.blobstore.integration.SwiftBlobLiveTest;
+import org.testng.annotations.Test;
+
+@Test(groups = "live", testName = "CloudFilesBlobLiveTest")
+public class CloudFilesBlobLiveTest extends SwiftBlobLiveTest {
+
+ public CloudFilesBlobLiveTest() {
+ provider = "rackspace-cloudfiles";
+ }
+
+ @Override
+ protected Properties setupProperties() {
+ Properties props = super.setupProperties();
+ setIfTestSystemPropertyPresent(props, API_KEY_CREDENTIALS);
+ return props;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/2ca0dac7/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/blobstore/integration/CloudFilesBlobSignerLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/blobstore/integration/CloudFilesBlobSignerLiveTest.java b/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/blobstore/integration/CloudFilesBlobSignerLiveTest.java
new file mode 100644
index 0000000..dea68f2
--- /dev/null
+++ b/apis/rackspace-cloudfiles/src/test/java/org/jclouds/rackspace/cloudfiles/v1/blobstore/integration/CloudFilesBlobSignerLiveTest.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.rackspace.cloudfiles.v1.blobstore.integration;
+
+import static org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityCredentialTypes.API_KEY_CREDENTIALS;
+
+import java.util.Properties;
+
+import org.jclouds.openstack.swift.v1.blobstore.integration.SwiftBlobSignerLiveTest;
+import org.testng.annotations.Test;
+
+@Test(groups = "live", testName = "CloudFilesBlobSignerLiveTest")
+public class CloudFilesBlobSignerLiveTest extends SwiftBlobSignerLiveTest {
+
+ public CloudFilesBlobSignerLiveTest() {
+ provider = "rackspace-cloudfiles";
+ }
+
+ @Override
+ protected Properties setupProperties() {
+ Properties props = super.setupProperties();
+ setIfTestSystemPropertyPresent(props, API_KEY_CREDENTIALS);
+ return props;
+ }
+}