You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ev...@apache.org on 2014/04/03 22:55:04 UTC

[2/5] Backport of OpenStack Swift/Rackspace Cloud Files as described in JCLOUDS-299 and JCLOUDS-423

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/cc81af6a/rackspace-cloudfiles-us/pom.xml
----------------------------------------------------------------------
diff --git a/rackspace-cloudfiles-us/pom.xml b/rackspace-cloudfiles-us/pom.xml
new file mode 100644
index 0000000..7f4f4cf
--- /dev/null
+++ b/rackspace-cloudfiles-us/pom.xml
@@ -0,0 +1,176 @@
+<?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.7.2-SNAPSHOT</version>
+  </parent>
+
+  <!-- TODO: when out of labs, switch to org.jclouds.provider -->
+  <groupId>org.apache.jclouds.labs</groupId>
+  <artifactId>rackspace-cloudfiles-us</artifactId>
+  <version>1.7.2-SNAPSHOT</version>
+  <name>jclouds Rackspace Cloud Files US provider</name>
+  <description>OpenStack Object Storage implementation targeted to Rackspace Cloud Files US</description>
+  <packaging>bundle</packaging>
+
+  <properties>
+    <!-- identity endpoint -->
+    <test.rackspace-cloudfiles-us.endpoint>https://identity.api.rackspacecloud.com/v2.0/</test.rackspace-cloudfiles-us.endpoint>
+    <test.rackspace-cloudfiles-us.api-version>1</test.rackspace-cloudfiles-us.api-version>
+    <test.rackspace-cloudfiles-us.build-version />
+    <test.rackspace-cloudfiles-us.identity>${test.rackspace-us.identity}</test.rackspace-cloudfiles-us.identity>
+    <test.rackspace-cloudfiles-us.credential>${test.rackspace-us.credential}</test.rackspace-cloudfiles-us.credential>    
+    <jclouds.osgi.export>org.jclouds.rackspace.cloudfiles.us*;version="${project.version}"</jclouds.osgi.export>
+    <jclouds.osgi.import>
+      org.jclouds.rest.internal;version="${jclouds.version}",
+      org.jclouds.labs*;version="${project.version}",
+      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>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <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>rackspace-cloudfiles</artifactId>
+      <version>${project.parent.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds.labs</groupId>
+      <artifactId>rackspace-cloudfiles</artifactId>
+      <version>${project.parent.version}</version>
+    </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</groupId>
+      <artifactId>jclouds-blobstore</artifactId>
+      <version>${project.parent.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </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.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>org.apache.jclouds.api</groupId>
+    	<artifactId>rackspace-cloudidentity</artifactId>
+    	<version>${project.parent.version}</version>
+    </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-us.endpoint>${test.rackspace-cloudfiles-us.endpoint}</test.rackspace-cloudfiles-us.endpoint>
+                    <test.rackspace-cloudfiles-us.api-version>${test.rackspace-cloudfiles-us.api-version}</test.rackspace-cloudfiles-us.api-version>
+                    <test.rackspace-cloudfiles-us.build-version>${test.rackspace-cloudfiles-us.build-version}</test.rackspace-cloudfiles-us.build-version>
+                    <test.rackspace-cloudfiles-us.identity>${test.rackspace-cloudfiles-us.identity}</test.rackspace-cloudfiles-us.identity>
+                    <test.rackspace-cloudfiles-us.credential>${test.rackspace-cloudfiles-us.credential}</test.rackspace-cloudfiles-us.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-labs-openstack/blob/cc81af6a/rackspace-cloudfiles-us/src/main/java/org/jclouds/rackspace/cloudfiles/us/CloudFilesUSProviderMetadata.java
----------------------------------------------------------------------
diff --git a/rackspace-cloudfiles-us/src/main/java/org/jclouds/rackspace/cloudfiles/us/CloudFilesUSProviderMetadata.java b/rackspace-cloudfiles-us/src/main/java/org/jclouds/rackspace/cloudfiles/us/CloudFilesUSProviderMetadata.java
new file mode 100644
index 0000000..beb9521
--- /dev/null
+++ b/rackspace-cloudfiles-us/src/main/java/org/jclouds/rackspace/cloudfiles/us/CloudFilesUSProviderMetadata.java
@@ -0,0 +1,145 @@
+/*
+ * 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.us;
+
+import static org.jclouds.location.reference.LocationConstants.ISO3166_CODES;
+import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGION;
+import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
+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.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.RegionModule;
+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.providers.ProviderMetadata;
+import org.jclouds.providers.internal.BaseProviderMetadata;
+import org.jclouds.rackspace.cloudfiles.v1.CloudFilesApiMetadata;
+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 com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+
+/**
+ * Implementation of {@link ProviderMetadata} for Rackspace Cloud Files US regions.
+ * 
+ * @author Jeremy Daggett
+ */
+public class CloudFilesUSProviderMetadata extends BaseProviderMetadata {
+   
+   /**
+    * @return The Builder object.
+    */
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   @Override
+   public Builder toBuilder() {
+      return builder().fromProviderMetadata(this);
+   }
+
+   /**
+    * Provider constructor.
+    */
+   public CloudFilesUSProviderMetadata() {
+      this(new Builder());
+   }
+
+   /**
+    * @param builder the Builder for the provider.
+    */
+   protected CloudFilesUSProviderMetadata(Builder builder) {
+      super(builder);
+   }
+
+   /**
+    * @return a {@link Properties} object containing the default provider properties.
+    */
+   public static Properties defaultProperties() {
+      Properties properties = new Properties();
+      properties.setProperty(CREDENTIAL_TYPE, CloudIdentityCredentialTypes.API_KEY_CREDENTIALS);
+      properties.setProperty(SERVICE_TYPE, ServiceType.OBJECT_STORE); 
+
+      properties.setProperty(PROPERTY_REGIONS, "ORD,DFW,IAD,SYD,HKG");
+      properties.setProperty(PROPERTY_REGION + ".ORD." + ISO3166_CODES, "US-IL");
+      properties.setProperty(PROPERTY_REGION + ".DFW." + ISO3166_CODES, "US-TX");
+      properties.setProperty(PROPERTY_REGION + ".IAD." + ISO3166_CODES, "US-VA");
+      properties.setProperty(PROPERTY_REGION + ".SYD." + ISO3166_CODES, "AU-NSW");
+      properties.setProperty(PROPERTY_REGION + ".HKG." + ISO3166_CODES, "HK");
+
+      return properties;
+   }
+
+   /**
+    * Builder pattern class.
+    */
+   public static class Builder extends BaseProviderMetadata.Builder {
+
+      protected Builder() {
+         id("rackspace-cloudfiles-us")
+         .name("Rackspace Cloud Files US")
+         .apiMetadata(new CloudFilesApiMetadata().toBuilder()
+               .identityName("${userName}")
+               .credentialName("${apiKey}")
+               .defaultEndpoint("https://identity.api.rackspacecloud.com/v2.0/")
+               .documentation(URI.create("http://docs.rackspace.com/files/api/v1/cf-devguide/content/index.html"))
+               .endpointName("Rackspace Cloud Identity service URL ending in /v2.0/")
+               .version("1.0")
+               .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())
+               .build())
+         .homepage(URI.create("http://www.rackspace.com/cloud/files"))
+         .console(URI.create("https://mycloud.rackspace.com"))
+         .linkedServices("rackspace-autoscale-us", "rackspace-cloudblockstorage-us",
+                         "rackspace-clouddatabases-us", "rackspace-clouddns-us",
+                         "rackspace-cloudidentity", "rackspace-cloudloadbalancers-us",
+                         "rackspace-cloudqueues-us")
+         .iso3166Codes("US-IL", "US-TX", "US-VA", "AU-NSW", "HK")
+         .defaultProperties(CloudFilesUSProviderMetadata.defaultProperties());
+         
+      }
+
+      @Override
+      public CloudFilesUSProviderMetadata build() {
+         return new CloudFilesUSProviderMetadata(this);
+      }
+
+      @Override
+      public Builder fromProviderMetadata(ProviderMetadata in) {
+         super.fromProviderMetadata(in);
+         return this;
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/cc81af6a/rackspace-cloudfiles-us/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata
----------------------------------------------------------------------
diff --git a/rackspace-cloudfiles-us/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata b/rackspace-cloudfiles-us/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata
new file mode 100644
index 0000000..cf4c3b4
--- /dev/null
+++ b/rackspace-cloudfiles-us/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata
@@ -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.us.CloudFilesUSProviderMetadata

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/cc81af6a/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/CloudFilesUSProviderTest.java
----------------------------------------------------------------------
diff --git a/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/CloudFilesUSProviderTest.java b/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/CloudFilesUSProviderTest.java
new file mode 100644
index 0000000..3a717e7
--- /dev/null
+++ b/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/CloudFilesUSProviderTest.java
@@ -0,0 +1,28 @@
+/*
+ * 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.us;
+
+import org.jclouds.providers.internal.BaseProviderMetadataTest;
+import org.jclouds.rackspace.cloudfiles.v1.CloudFilesApiMetadata;
+import org.testng.annotations.Test;
+
+@Test(groups = "unit", testName = "CloudFilesUSProviderTest")
+public class CloudFilesUSProviderTest extends BaseProviderMetadataTest {
+   public CloudFilesUSProviderTest() {
+      super(new CloudFilesUSProviderMetadata(), new CloudFilesApiMetadata());
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/cc81af6a/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSBlobIntegrationLiveTest.java
----------------------------------------------------------------------
diff --git a/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSBlobIntegrationLiveTest.java b/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSBlobIntegrationLiveTest.java
new file mode 100644
index 0000000..b684e89
--- /dev/null
+++ b/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSBlobIntegrationLiveTest.java
@@ -0,0 +1,27 @@
+/*
+ * 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.us.blobstore.integration;
+
+import org.jclouds.rackspace.cloudfiles.v1.blobstore.integration.CloudFilesBlobIntegrationLiveTest;
+import org.testng.annotations.Test;
+
+@Test(groups = "live", testName = "CloudFilesUSBlobIntegrationLiveTest")
+public class CloudFilesUSBlobIntegrationLiveTest extends CloudFilesBlobIntegrationLiveTest {
+   public CloudFilesUSBlobIntegrationLiveTest() {
+      provider = "rackspace-cloudfiles-us";
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/cc81af6a/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSBlobLiveTest.java
----------------------------------------------------------------------
diff --git a/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSBlobLiveTest.java b/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSBlobLiveTest.java
new file mode 100644
index 0000000..8eb5385
--- /dev/null
+++ b/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSBlobLiveTest.java
@@ -0,0 +1,27 @@
+/*
+ * 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.us.blobstore.integration;
+
+import org.jclouds.rackspace.cloudfiles.v1.blobstore.integration.CloudFilesBlobLiveTest;
+import org.testng.annotations.Test;
+
+@Test(groups = "live", testName = "CloudFilesUSBlobLiveTest")
+public class CloudFilesUSBlobLiveTest extends CloudFilesBlobLiveTest {
+   public CloudFilesUSBlobLiveTest() {
+      provider = "rackspace-cloudfiles-us";
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/cc81af6a/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSBlobSignerLiveTest.java
----------------------------------------------------------------------
diff --git a/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSBlobSignerLiveTest.java b/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSBlobSignerLiveTest.java
new file mode 100644
index 0000000..5255de2
--- /dev/null
+++ b/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSBlobSignerLiveTest.java
@@ -0,0 +1,27 @@
+/*
+ * 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.us.blobstore.integration;
+
+import org.jclouds.rackspace.cloudfiles.v1.blobstore.integration.CloudFilesBlobSignerLiveTest;
+import org.testng.annotations.Test;
+
+@Test(groups = "live", testName = "CloudFilesUSBlobSignerLiveTest")
+public class CloudFilesUSBlobSignerLiveTest extends CloudFilesBlobSignerLiveTest {
+   public CloudFilesUSBlobSignerLiveTest() {
+      provider = "rackspace-cloudfiles-us";
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/cc81af6a/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSContainerIntegrationLiveTest.java
----------------------------------------------------------------------
diff --git a/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSContainerIntegrationLiveTest.java b/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSContainerIntegrationLiveTest.java
new file mode 100644
index 0000000..2fe511e
--- /dev/null
+++ b/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSContainerIntegrationLiveTest.java
@@ -0,0 +1,27 @@
+/*
+ * 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.us.blobstore.integration;
+
+import org.jclouds.rackspace.cloudfiles.v1.blobstore.integration.CloudFilesContainerIntegrationLiveTest;
+import org.testng.annotations.Test;
+
+@Test(groups = "live", testName = "CloudFilesUSContainerIntegrationLiveTest")
+public class CloudFilesUSContainerIntegrationLiveTest extends CloudFilesContainerIntegrationLiveTest {
+   public CloudFilesUSContainerIntegrationLiveTest() {
+      provider = "rackspace-cloudfiles-us";
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/cc81af6a/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSContainerLiveTest.java
----------------------------------------------------------------------
diff --git a/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSContainerLiveTest.java b/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSContainerLiveTest.java
new file mode 100644
index 0000000..44daffd
--- /dev/null
+++ b/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSContainerLiveTest.java
@@ -0,0 +1,27 @@
+/*
+ * 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.us.blobstore.integration;
+
+import org.jclouds.rackspace.cloudfiles.v1.blobstore.integration.CloudFilesContainerLiveTest;
+import org.testng.annotations.Test;
+
+@Test(groups = "live", testName = "CloudFilesUSContainerLiveTest")
+public class CloudFilesUSContainerLiveTest extends CloudFilesContainerLiveTest {
+   public CloudFilesUSContainerLiveTest() {
+      provider = "rackspace-cloudfiles-us";
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/cc81af6a/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSServiceIntegrationLiveTest.java
----------------------------------------------------------------------
diff --git a/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSServiceIntegrationLiveTest.java b/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSServiceIntegrationLiveTest.java
new file mode 100644
index 0000000..698b733
--- /dev/null
+++ b/rackspace-cloudfiles-us/src/test/java/org/jclouds/rackspace/cloudfiles/us/blobstore/integration/CloudFilesUSServiceIntegrationLiveTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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.us.blobstore.integration;
+
+import java.util.Set;
+
+import org.jclouds.rackspace.cloudfiles.v1.blobstore.integration.CloudFilesServiceIntegrationLiveTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+@Test(groups = "live", testName = "CloudFilesUSServiceIntegrationLiveTest")
+public class CloudFilesUSServiceIntegrationLiveTest extends CloudFilesServiceIntegrationLiveTest {
+   public CloudFilesUSServiceIntegrationLiveTest() {
+      provider = "rackspace-cloudfiles-us";
+   }
+
+   @Override
+   protected Set<String> getIso3166Codes() {
+      return ImmutableSet.<String> of("US-IL", "US-TX", "US-VA", "AU-NSW", "HK");
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/cc81af6a/rackspace-cloudfiles-us/src/test/resources/logback.xml
----------------------------------------------------------------------
diff --git a/rackspace-cloudfiles-us/src/test/resources/logback.xml b/rackspace-cloudfiles-us/src/test/resources/logback.xml
new file mode 100644
index 0000000..ce891f1
--- /dev/null
+++ b/rackspace-cloudfiles-us/src/test/resources/logback.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<!--
+
+    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.
+
+-->
+<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>

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/cc81af6a/rackspace-cloudfiles/README.md
----------------------------------------------------------------------
diff --git a/rackspace-cloudfiles/README.md b/rackspace-cloudfiles/README.md
new file mode 100644
index 0000000..1142323
--- /dev/null
+++ b/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-labs-openstack/blob/cc81af6a/rackspace-cloudfiles/pom.xml
----------------------------------------------------------------------
diff --git a/rackspace-cloudfiles/pom.xml b/rackspace-cloudfiles/pom.xml
new file mode 100644
index 0000000..efe2859
--- /dev/null
+++ b/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.7.2-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.7.2-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-labs-openstack/blob/cc81af6a/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/CloudFilesApi.java
----------------------------------------------------------------------
diff --git a/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/CloudFilesApi.java b/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/CloudFilesApi.java
new file mode 100644
index 0000000..19667d7
--- /dev/null
+++ b/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-labs-openstack/blob/cc81af6a/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/CloudFilesApiMetadata.java
----------------------------------------------------------------------
diff --git a/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/CloudFilesApiMetadata.java b/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/CloudFilesApiMetadata.java
new file mode 100644
index 0000000..17baef0
--- /dev/null
+++ b/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/CloudFilesApiMetadata.java
@@ -0,0 +1,103 @@
+/*
+ * 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.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-labs-openstack/blob/cc81af6a/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/binders/BindCDNPurgeEmailAddressesToHeaders.java
----------------------------------------------------------------------
diff --git a/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/binders/BindCDNPurgeEmailAddressesToHeaders.java b/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/binders/BindCDNPurgeEmailAddressesToHeaders.java
new file mode 100644
index 0000000..792657a
--- /dev/null
+++ b/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/binders/BindCDNPurgeEmailAddressesToHeaders.java
@@ -0,0 +1,55 @@
+/*
+ * 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.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-labs-openstack/blob/cc81af6a/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/config/CloudFilesHttpApiModule.java
----------------------------------------------------------------------
diff --git a/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/config/CloudFilesHttpApiModule.java b/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/config/CloudFilesHttpApiModule.java
new file mode 100644
index 0000000..092fec9
--- /dev/null
+++ b/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-labs-openstack/blob/cc81af6a/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/domain/CDNContainer.java
----------------------------------------------------------------------
diff --git a/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/domain/CDNContainer.java b/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/domain/CDNContainer.java
new file mode 100644
index 0000000..590bccb
--- /dev/null
+++ b/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-labs-openstack/blob/cc81af6a/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/features/CDNApi.java
----------------------------------------------------------------------
diff --git a/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/features/CDNApi.java b/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/features/CDNApi.java
new file mode 100644
index 0000000..98e5c54
--- /dev/null
+++ b/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/features/CDNApi.java
@@ -0,0 +1,204 @@
+/*
+ * 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.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-labs-openstack/blob/cc81af6a/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/functions/ParseCDNContainerFromHeaders.java
----------------------------------------------------------------------
diff --git a/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/functions/ParseCDNContainerFromHeaders.java b/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/functions/ParseCDNContainerFromHeaders.java
new file mode 100644
index 0000000..e551ab1
--- /dev/null
+++ b/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-labs-openstack/blob/cc81af6a/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/functions/ParseCDNContainerURIFromHeaders.java
----------------------------------------------------------------------
diff --git a/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/functions/ParseCDNContainerURIFromHeaders.java b/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/functions/ParseCDNContainerURIFromHeaders.java
new file mode 100644
index 0000000..42ed1f7
--- /dev/null
+++ b/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/functions/ParseCDNContainerURIFromHeaders.java
@@ -0,0 +1,44 @@
+/*
+ * 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.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-labs-openstack/blob/cc81af6a/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/functions/RegionToCDNEndpoint.java
----------------------------------------------------------------------
diff --git a/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/functions/RegionToCDNEndpoint.java b/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/functions/RegionToCDNEndpoint.java
new file mode 100644
index 0000000..7ce64e7
--- /dev/null
+++ b/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/functions/RegionToCDNEndpoint.java
@@ -0,0 +1,74 @@
+/*
+ * 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.suppliers.RegionIdToURISupplier;
+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-labs-openstack/blob/cc81af6a/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/handlers/CloudFilesErrorHandler.java
----------------------------------------------------------------------
diff --git a/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/handlers/CloudFilesErrorHandler.java b/rackspace-cloudfiles/src/main/java/org/jclouds/rackspace/cloudfiles/v1/handlers/CloudFilesErrorHandler.java
new file mode 100644
index 0000000..1e69b23
--- /dev/null
+++ b/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);
+   }
+}