You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ad...@apache.org on 2014/11/13 20:07:05 UTC

[4/4] jclouds-labs-google git commit: Dedupe code between google cloud products.

Dedupe code between google cloud products.


Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/commit/f191c8fb
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/tree/f191c8fb
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/diff/f191c8fb

Branch: refs/heads/master
Commit: f191c8fb00dfb8146584083b1a1a158971e1695c
Parents: 6276670
Author: Adrian Cole <ac...@twitter.com>
Authored: Thu Nov 13 10:00:30 2014 -0800
Committer: Adrian Cole <ac...@twitter.com>
Committed: Thu Nov 13 11:02:44 2014 -0800

----------------------------------------------------------------------
 google-cloud-storage/README.md                  |  36 +--
 google-cloud-storage/pom.xml                    | 253 ++++++++++---------
 .../GoogleCloudStorageApiMetadata.java          |  36 ++-
 .../GoogleCloudStorageFallbacks.java            |  18 --
 .../GoogleCloudStorageProviderMetadata.java     |  72 ++++++
 .../blobstore/GCSBlobStore.java                 |  13 +-
 .../config/GCSBlobStoreContextModule.java       |  32 ---
 ...oogleCloudStorageBlobStoreContextModule.java |  33 +++
 .../functions/ObjectListToStorageMetadata.java  |   9 +-
 .../MultipartUploadSlicingAlgorithm.java        |   9 +-
 .../config/GoogleCloudStorageHttpApiModule.java |  40 +--
 .../config/GoogleCloudStorageParserModule.java  |   9 +
 .../googlecloudstorage/config/UserProject.java  |  33 ---
 .../googlecloudstorage/domain/Bucket.java       |   4 +-
 .../googlecloudstorage/domain/GCSObject.java    |   2 +-
 .../googlecloudstorage/domain/ListPage.java     |  57 -----
 .../domain/ListPageWithPrefixes.java            |  58 +++++
 .../googlecloudstorage/features/BucketApi.java  |   5 +-
 .../googlecloudstorage/features/ObjectApi.java  |  13 +-
 .../GoogleCloudStorageRedirectRetryHandler.java |   1 +
 .../internal/NullSafeCopies.java                |  39 ---
 .../googlecloudstorage/options/ListOptions.java |   8 +-
 .../parser/ParseToPayloadEnclosing.java         |   1 +
 .../reference/GoogleCloudStorageConstants.java  |   2 -
 .../GoogleCloudStorageApiMetadataTest.java      |  31 ---
 ...StorageAuthenticatedRestContextLiveTest.java |  34 ---
 .../GoogleCloudStorageProviderMetadataTest.java |  34 +++
 .../integration/GCSBlobIntegrationLiveTest.java |  16 +-
 .../blobstore/integration/GCSBlobLiveTest.java  |   6 +
 .../GCSContainerIntegrationLiveTest.java        |   7 +-
 .../integration/GCSContainerLiveTest.java       |   7 +
 .../features/BucketApiExpectTest.java           |   5 +-
 .../features/BucketApiLiveTest.java             |   3 +-
 .../features/ObjectApiLiveTest.java             |   6 +-
 .../BaseGoogleCloudStorageApiExpectTest.java    |   3 +-
 .../BaseGoogleCloudStorageApiLiveTest.java      |  17 +-
 .../BaseGoogleCloudStorageExpectTest.java       |  21 +-
 .../BaseGoogleCloudStorageParseTest.java        |   3 +-
 .../parse/FullBucketGetTest.java                |   2 +-
 .../parse/NoAclBucketListTest.java              |   5 +-
 .../src/test/resources/logback.xml              |  83 ++++++
 google-compute-engine/pom.xml                   |   8 +-
 .../GoogleComputeEngineApi.java                 |   2 +-
 .../GoogleComputeEngineApiMetadata.java         |   6 +-
 .../compute/GoogleComputeEngineService.java     |   2 +-
 .../GoogleComputeEngineServiceAdapter.java      |   2 +-
 ...ogleComputeEngineSecurityGroupExtension.java |   2 +-
 .../functions/NetworkToSecurityGroup.java       |   2 +-
 .../config/CurrentProject.java                  |  31 ---
 .../GoogleComputeEngineHttpApiModule.java       |  12 +-
 .../config/GoogleComputeEngineParserModule.java |  86 +------
 .../config/GoogleComputeEngineProperties.java   |  21 +-
 .../googlecomputeengine/domain/Firewall.java    |   2 +-
 .../googlecomputeengine/domain/Instance.java    |   2 +-
 .../googlecomputeengine/domain/ListPage.java    |  51 ----
 .../googlecomputeengine/domain/MachineType.java |   2 +-
 .../googlecomputeengine/domain/Operation.java   |   2 +-
 .../googlecomputeengine/domain/Project.java     |   2 +-
 .../googlecomputeengine/domain/Region.java      |   2 +-
 .../googlecomputeengine/domain/Route.java       |   2 +-
 .../googlecomputeengine/domain/TargetPool.java  |   2 +-
 .../googlecomputeengine/domain/Zone.java        |   2 +-
 .../features/AddressApi.java                    |   2 +-
 .../features/AggregatedListApi.java             |   2 +-
 .../googlecomputeengine/features/DiskApi.java   |   2 +-
 .../features/DiskTypeApi.java                   |   2 +-
 .../features/FirewallApi.java                   |   4 +-
 .../features/ForwardingRuleApi.java             |   2 +-
 .../features/HttpHealthCheckApi.java            |   2 +-
 .../googlecomputeengine/features/ImageApi.java  |   4 +-
 .../features/InstanceApi.java                   |   2 +-
 .../features/MachineTypeApi.java                |   2 +-
 .../features/NetworkApi.java                    |   2 +-
 .../features/OperationApi.java                  |   4 +-
 .../googlecomputeengine/features/RegionApi.java |   2 +-
 .../googlecomputeengine/features/RouteApi.java  |   2 +-
 .../features/SnapshotApi.java                   |   2 +-
 .../features/TargetPoolApi.java                 |   2 +-
 .../googlecomputeengine/features/ZoneApi.java   |   2 +-
 .../internal/AdvancingIterator.java             |  48 ----
 .../internal/BaseArg0ToIteratorOfListPage.java  |  42 +--
 .../BaseCallerArg0ToIteratorOfListPage.java     |  42 +--
 .../internal/BaseToIteratorOfListPage.java      |  33 +--
 .../googlecomputeengine/internal/ListPages.java |  56 ----
 .../internal/NullSafeCopies.java                |  39 ---
 .../googlecomputeengine/internal/PATCH.java     |  35 ---
 .../options/ListOptions.java                    |  11 +-
 ...eEngineAuthenticatedRestContextLiveTest.java |  40 ---
 ...GoogleComputeEngineProviderMetadataTest.java |   2 +-
 .../GoogleComputeEngineServiceLiveTest.java     |   4 +-
 ...uteEngineSecurityGroupExtensionLiveTest.java |   4 +-
 .../functions/NetworkToSecurityGroupTest.java   |   4 +-
 .../UseApiToResolveProjectNameMockTest.java     |   2 +-
 .../features/AddressApiLiveTest.java            |   2 +-
 .../features/AggregatedListApiLiveTest.java     |   2 +-
 .../features/DiskApiLiveTest.java               |   2 +-
 .../features/DiskTypeApiLiveTest.java           |   2 +-
 .../features/FirewallApiLiveTest.java           |   2 +-
 .../features/ForwardingRuleApiLiveTest.java     |   2 +-
 .../features/HttpHealthCheckApiLiveTest.java    |   2 +-
 .../features/ImageApiLiveTest.java              |   2 +-
 .../features/InstanceApiLiveTest.java           |   2 +-
 .../features/MachineTypeApiLiveTest.java        |   2 +-
 .../features/NetworkApiLiveTest.java            |   2 +-
 .../features/OperationApiExpectTest.java        |   7 +-
 .../features/OperationApiLiveTest.java          |   2 +-
 .../features/RegionApiLiveTest.java             |   2 +-
 .../features/RouteApiLiveTest.java              |   2 +-
 .../features/SnapshotApiLiveTest.java           |   2 +-
 .../features/TargetPoolApiLiveTest.java         |   2 +-
 .../features/ZoneApiLiveTest.java               |   2 +-
 .../BaseGoogleComputeEngineApiLiveTest.java     |   8 +-
 .../BaseGoogleComputeEngineApiMockTest.java     |   4 +-
 .../BaseGoogleComputeEngineExpectTest.java      |   2 +-
 .../internal/TestProperties.java                |  53 ----
 .../ToIteratorOfListPageExpectTest.java         |  21 +-
 .../parse/ParseAddressListTest.java             |   5 +-
 .../parse/ParseDiskListTest.java                |   5 +-
 .../parse/ParseDiskTypeListTest.java            |   5 +-
 .../parse/ParseFirewallListTest.java            |   5 +-
 .../parse/ParseForwardingRuleListTest.java      |   5 +-
 .../parse/ParseGlobalOperationListTest.java     |   5 +-
 .../parse/ParseHttpHealthCheckListTest.java     |   5 +-
 .../parse/ParseImageListTest.java               |   5 +-
 .../parse/ParseInstanceListTest.java            |   5 +-
 .../parse/ParseMachineTypeListTest.java         |   5 +-
 .../parse/ParseNetworkListTest.java             |   5 +-
 .../parse/ParseRegionListTest.java              |   5 +-
 .../parse/ParseRouteListTest.java               |   5 +-
 .../parse/ParseSnapshotListTest.java            |   5 +-
 .../parse/ParseTargetPoolListTest.java          |   5 +-
 .../parse/ParseZoneListTest.java                |   5 +-
 googlecloud/pom.xml                             |  62 +++++
 .../googlecloud/config/CurrentProject.java      |  50 ++++
 .../config/GoogleCloudProperties.java           |  40 +++
 .../config/ListPageAdapterFactory.java          | 109 ++++++++
 .../googlecloud/domain/ForwardingListPage.java  |  51 ++++
 .../jclouds/googlecloud/domain/ListPage.java    |  28 ++
 .../googlecloud/internal/AdvancingIterator.java |  48 ++++
 .../internal/BaseArg0ToIteratorOfListPage.java  |  58 +++++
 .../BaseCallerArg0ToIteratorOfListPage.java     |  58 +++++
 .../internal/BaseToIteratorOfListPage.java      |  49 ++++
 .../jclouds/googlecloud/internal/ListPages.java |  57 +++++
 .../googlecloud/internal/NullSafeCopies.java    |  39 +++
 .../googlecloud/options/ListOptions.java        |  30 +++
 .../googlecloud/internal/TestProperties.java    |  85 +++++++
 .../org/jclouds/oauth/v2/OAuthTestUtils.java    |   1 +
 pom.xml                                         |   1 +
 148 files changed, 1474 insertions(+), 1212 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/README.md
----------------------------------------------------------------------
diff --git a/google-cloud-storage/README.md b/google-cloud-storage/README.md
index 09f408b..59adad9 100644
--- a/google-cloud-storage/README.md
+++ b/google-cloud-storage/README.md
@@ -1,15 +1,18 @@
 jclouds Google Cloud Storage Provider
-===========================================================
+======
 Make sure both Google Cloud Storage and Google Cloud Storage JSON API are enabled for the project
 (check from Developers Console -> Api&auth -> APIs)
 
-* Q. What is the identity for GCE?
+FAQ:
+--------
 
-A. the identity is the developer email which can be obtained from the admin GUI. Its usually something in the form: <my account id>@developer.gserviceaccount.com
+* Q. What is the identity for Google Cloud Storage?
 
-* Q. What is the credential for GCE
+A. the identity is the developer email which can be obtained from the admin GUI. Its usually something in the form: [PROJECT_ID](https://cloud.google.com/compute/docs/overview#projectids)@developer.gserviceaccount.com
 
-A. the credential is a private key, in pem format. It can be extracted from the p12 keystore that is obtained when creating a "Service Account" (in the GUI: Developers Console(For the project) -> APIs and Auth -> Create New Client ID -> "Service Account"
+* Q. What is the credential for Google Cloud Storage
+
+A. the credential is a private key, in pem format. It can be extracted from the p12 keystore that is obtained when creating a "Service Account" (in the GUI: Google apis console > Api Access > Create another client ID > "Service Account"
 
 * Q. How to convert a p12 keystore into a pem format jclouds Google Cloud Storage can handle:
 
@@ -25,23 +28,24 @@ The last file (<my_key>.pem) should contain the pk that needs to be passed to `C
 
 
 Running the live tests:
----------------------------------------------------------------
+--------
 
 1. Place the following in your ~/.m2/settings.xml in a profile enabled when live:
-
 ```
-<properties>
-    <test.google-cloud-storage.identity>Email address associated with service account</test.google-cloud-storage.identity>
-    <!-- this text is literally from your <my_key>.pem -->
+    <test.google-cloud-storage.identity>PROJECT_ID@developer.gserviceaccount.com</test.google-cloud-storage.identity>
     <test.google-cloud-storage.credential>-----BEGIN RSA PRIVATE KEY-----
 MIICXgIBAAKBgQRRbRqVDtJLN1MO/xJoKqZuphDeBh5jIKueW3aNIiWs1XFcct+h
-...
+-- this text is literally from your <my_key>.pem
 aH7xmpHSTbbXmQkuuv+z8EKijigprd/FoJpTX1f5/R+4wQ==
 -----END RSA PRIVATE KEY-----</test.google-cloud-storage.credential>
-    <test.google-cloud-storage.project-number>123451234</test.google-cloud-storage.project-number>
-</properties>
+  </properties>
+```
+Or, if using an existing OAuth Bearer Token for authentication.
+```
+    <test.google-cloud-storage.identity>PROJECT_ID@developer.gserviceaccount.com</test.google-cloud-storage.identity>
+    <test.google-cloud-storage.credential>EXISTING_BEARER_TOKEN</test.google-cloud-storage.credential>
+    <test.jclouds.oauth.credential-type>bearerTokenCredentials</test.jclouds.oauth.credential-type>
+  </properties>
 ```
 
-Example identity :- 123451234-abcd01234efgh@developer.gserviceaccount.com (NUMERIC_PREFIX-ALPHANEUMERIC_SUFFIX@developer.gserviceaccount.com)
-
-2. mvn integration-test -pl google-cloud-storage -Plive
+2. mvn clean install -Plive 

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/pom.xml
----------------------------------------------------------------------
diff --git a/google-cloud-storage/pom.xml b/google-cloud-storage/pom.xml
index 7d9fb39..c505774 100644
--- a/google-cloud-storage/pom.xml
+++ b/google-cloud-storage/pom.xml
@@ -1,5 +1,6 @@
 <?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.
@@ -14,131 +15,137 @@
     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>
+<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.labs</groupId>
+        <artifactId>jclouds-labs-google</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+
+    <!-- TODO: when out of labs, switch to org.jclouds.provider -->
     <groupId>org.apache.jclouds.labs</groupId>
-    <artifactId>jclouds-labs-google</artifactId>
-    <version>2.0.0-SNAPSHOT</version>
-  </parent>
-	<!-- TODO: when out of labs, switch to org.jclouds.provider -->
-  <groupId>org.apache.jclouds.labs</groupId>
-  <artifactId>google-cloud-storage</artifactId>
-  <name>jclouds Google Cloud Storage provider</name>
-  <description>jclouds components to access Google Cloud Storage</description>
+    <artifactId>google-cloud-storage</artifactId>
+    <name>jclouds Google Cloud Storage provider</name>
+    <description>jclouds components to access Google Cloud Storage</description>
 
-  <properties>
-    <test.google-cloud-storage.identity>  Email_Address_Associated_With_Service_Account</test.google-cloud-storage.identity>
-    <test.google-cloud-storage.credential>Private_Key_Associated__With_Service Account</test.google-cloud-storage.credential>
-    <test.google-cloud-storage.project-number>The Account Project number</test.google-cloud-storage.project-number>
-    <test.google-cloud-storage.api-version>v1</test.google-cloud-storage.api-version>
-    <test.google-cloud-storage.build-version />
-  </properties>
+    <properties>
+        <test.google-cloud-storage.identity>client_email which usually looks like project_id@developer.gserviceaccount.com</test.google-cloud-storage.identity>
+        <test.google-cloud-storage.credential>Private key (PEM encoded PKCS12 file or literal) associated with the client_email</test.google-cloud-storage.credential>
+        <!-- Add this property to use a different project, or avoid looking up the project for each test. -->
+        <test.jclouds.googlecloud.project-name></test.jclouds.googlecloud.project-name>
+        <test.jclouds.oauth.credential-type>p12PrivateKeyCredentials</test.jclouds.oauth.credential-type>
+        <test.google-cloud-storage.api-version>v1</test.google-cloud-storage.api-version>
+        <test.google-cloud-storage.build-version/>
+    </properties>
 
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.jclouds</groupId>
-      <artifactId>jclouds-core</artifactId>
-      <version>${jclouds.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.jclouds.labs</groupId>
-      <artifactId>oauth</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.jclouds.labs</groupId>
-      <artifactId>oauth</artifactId>
-      <version>${project.version}</version>
-      <type>test-jar</type>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.jclouds</groupId>
-      <artifactId>jclouds-blobstore</artifactId>
-      <version>${jclouds.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.google.auto.value</groupId>
-      <artifactId>auto-value</artifactId>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.jclouds</groupId>
-      <artifactId>jclouds-blobstore</artifactId>
-      <version>${jclouds.version}</version>
-      <type>test-jar</type>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.jclouds</groupId>
-      <artifactId>jclouds-core</artifactId>
-      <version>${jclouds.version}</version>
-      <type>test-jar</type>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.jclouds.driver</groupId>
-      <artifactId>jclouds-slf4j</artifactId>
-      <version>${jclouds.version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.jclouds.driver</groupId>
-      <artifactId>jclouds-sshj</artifactId>
-      <version>${jclouds.version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>ch.qos.logback</groupId>
-      <artifactId>logback-classic</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.assertj</groupId>
-      <artifactId>assertj-core</artifactId>
-      <version>1.6.1</version>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
-  <profiles>
-    <profile>
-      <id>live</id>
-      <build>
-        <plugins>
-          <plugin>
-            <groupId>org.apache.maven.plugins</groupId>
-            <artifactId>maven-surefire-plugin</artifactId>
-            <executions>
-              <execution>
-                <id>default-test</id>
-                <configuration>
-                  <skipTests>true</skipTests>
-                </configuration>
-              </execution>
-              <execution>
-                <id>integration</id>
-                <phase>integration-test</phase>
-                <goals>
-                  <goal>test</goal>
-                </goals>
-                <configuration>
-                  <systemPropertyVariables>
-                    <jclouds.blobstore.httpstream.url>${jclouds.blobstore.httpstream.url}</jclouds.blobstore.httpstream.url>
-                    <jclouds.blobstore.httpstream.md5>${jclouds.blobstore.httpstream.md5}</jclouds.blobstore.httpstream.md5>
-                    <test.google-cloud-storage.identity>${test.google-cloud-storage.identity}</test.google-cloud-storage.identity>
-                    <test.google-cloud-storage.credential>${test.google-cloud-storage.credential}</test.google-cloud-storage.credential>
-                    <test.google-cloud-storage.project-number>${test.google-cloud-storage.project-number}</test.google-cloud-storage.project-number>
-                    <test.google-cloud-storage.api-version>${test.google-cloud-storage.api-version}</test.google-cloud-storage.api-version>
-                    <test.google-cloud-storage.build-version>${test.google-cloud-storage.build-version}</test.google-cloud-storage.build-version>
-                  </systemPropertyVariables>
-                </configuration>
-              </execution>
-            </executions>
-          </plugin>
-        </plugins>
-      </build>
-    </profile>
-  </profiles>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.jclouds</groupId>
+            <artifactId>jclouds-core</artifactId>
+            <version>${jclouds.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds.labs</groupId>
+            <artifactId>googlecloud</artifactId>
+            <version>${project.version}</version>
+            <type>jar</type>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds.labs</groupId>
+            <artifactId>googlecloud</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds</groupId>
+            <artifactId>jclouds-blobstore</artifactId>
+            <version>${jclouds.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.auto.value</groupId>
+            <artifactId>auto-value</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds</groupId>
+            <artifactId>jclouds-blobstore</artifactId>
+            <version>${jclouds.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds</groupId>
+            <artifactId>jclouds-core</artifactId>
+            <version>${jclouds.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds.driver</groupId>
+            <artifactId>jclouds-slf4j</artifactId>
+            <version>${jclouds.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>
+          <exclusions>
+            <!-- Already provided by jclouds-sshj -->
+            <exclusion>
+              <groupId>org.bouncycastle</groupId>
+              <artifactId>bcprov-jdk15on</artifactId>
+            </exclusion>
+          </exclusions>
+        </dependency>
+    </dependencies>
+    <profiles>
+        <profile>
+            <id>live</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>default-test</id>
+                                <configuration>
+                                    <skipTests>true</skipTests>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>integration</id>
+                                <phase>integration-test</phase>
+                                <goals>
+                                    <goal>test</goal>
+                                </goals>
+                                <configuration>
+                                    <threadCount>1</threadCount>
+                                    <systemPropertyVariables>
+                                        <test.google-cloud-storage.identity>${test.google-cloud-storage.identity}</test.google-cloud-storage.identity>
+                                        <test.google-cloud-storage.credential>${test.google-cloud-storage.credential}</test.google-cloud-storage.credential>
+                                        <test.jclouds.googlecloud.project-name>${test.jclouds.googlecloud.project-name}</test.jclouds.googlecloud.project-name>
+                                        <test.jclouds.oauth.credential-type>${test.jclouds.oauth.credential-type}</test.jclouds.oauth.credential-type>
+                                        <test.google-cloud-storage.api-version>${test.google-cloud-storage.api-version}</test.google-cloud-storage.api-version>
+                                        <test.google-cloud-storage.build-version>${test.google-cloud-storage.build-version}</test.google-cloud-storage.build-version>
+                                    </systemPropertyVariables>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
 </project>

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApiMetadata.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApiMetadata.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApiMetadata.java
index 604e4ed..03129a5 100644
--- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApiMetadata.java
+++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApiMetadata.java
@@ -17,7 +17,6 @@
 package org.jclouds.googlecloudstorage;
 
 import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
-import static org.jclouds.googlecloudstorage.reference.GoogleCloudStorageConstants.GCS_PROVIDER_NAME;
 import static org.jclouds.googlecloudstorage.reference.GoogleCloudStorageConstants.OPERATION_COMPLETE_INTERVAL;
 import static org.jclouds.googlecloudstorage.reference.GoogleCloudStorageConstants.OPERATION_COMPLETE_TIMEOUT;
 import static org.jclouds.oauth.v2.config.OAuthProperties.AUDIENCE;
@@ -27,20 +26,18 @@ import static org.jclouds.reflect.Reflection2.typeToken;
 import java.net.URI;
 import java.util.Properties;
 
-import org.jclouds.apis.ApiMetadata;
 import org.jclouds.blobstore.BlobStoreContext;
-import org.jclouds.googlecloudstorage.blobstore.config.GCSBlobStoreContextModule;
+import org.jclouds.googlecloud.config.CurrentProject;
+import org.jclouds.googlecloudstorage.blobstore.config.GoogleCloudStorageBlobStoreContextModule;
 import org.jclouds.googlecloudstorage.config.GoogleCloudStorageHttpApiModule;
 import org.jclouds.googlecloudstorage.config.GoogleCloudStorageParserModule;
 import org.jclouds.oauth.v2.config.OAuthAuthenticationModule;
 import org.jclouds.oauth.v2.config.OAuthModule;
 import org.jclouds.rest.internal.BaseHttpApiMetadata;
 
-import com.google.auto.service.AutoService;
 import com.google.common.collect.ImmutableSet;
 import com.google.inject.Module;
 
-@AutoService(ApiMetadata.class)
 public class GoogleCloudStorageApiMetadata extends BaseHttpApiMetadata<GoogleCloudStorageApi> {
 
    @Override
@@ -69,20 +66,21 @@ public class GoogleCloudStorageApiMetadata extends BaseHttpApiMetadata<GoogleClo
 
    public static class Builder extends BaseHttpApiMetadata.Builder<GoogleCloudStorageApi, Builder> {
       protected Builder() {
-         id(GCS_PROVIDER_NAME)
-                  .name("Google Cloud Storage Api ")
-                  .identityName("Email associated with the Google API client_id")
-                  .credentialName("Private key literal associated with the Google API client_id")
-                  .documentation(URI.create("https://developers.google.com/storage/docs/json_api"))
-                  .version("v1")
-                  .defaultEndpoint("https://www.googleapis.com")
-                  .defaultProperties(GoogleCloudStorageApiMetadata.defaultProperties())
-                  .view(typeToken(BlobStoreContext.class))
-                  .defaultModules(
-                           ImmutableSet.<Class<? extends Module>> of(GoogleCloudStorageParserModule.class,
-                                 OAuthAuthenticationModule.class, OAuthModule.class,
-                                 GoogleCloudStorageHttpApiModule.class, GCSBlobStoreContextModule.class));
-
+         id("google-cloud-storage")
+         .name("Google Cloud Storage Api")
+         .identityName(CurrentProject.ClientEmail.DESCRIPTION)
+         .credentialName("PEM encoded P12 private key associated with client_email")
+         .documentation(URI.create("https://developers.google.com/storage/docs/json_api"))
+         .version("v1")
+         .defaultEndpoint("https://www.googleapis.com")
+         .defaultProperties(GoogleCloudStorageApiMetadata.defaultProperties())
+         .view(typeToken(BlobStoreContext.class))
+         .defaultModules(ImmutableSet.<Class<? extends Module>> builder()
+                 .add(GoogleCloudStorageParserModule.class)
+                 .add(OAuthAuthenticationModule.class)
+                 .add(OAuthModule.class)
+                 .add(GoogleCloudStorageHttpApiModule.class)
+                 .add(GoogleCloudStorageBlobStoreContextModule.class).build());
       }
 
       @Override

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageFallbacks.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageFallbacks.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageFallbacks.java
index 5855015..d19175a 100644
--- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageFallbacks.java
+++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageFallbacks.java
@@ -18,14 +18,8 @@ package org.jclouds.googlecloudstorage;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Throwables.propagate;
-import static org.jclouds.Fallbacks.valOnNotFoundOr404;
-
-import java.util.Iterator;
 
 import org.jclouds.Fallback;
-import org.jclouds.googlecloudstorage.domain.ListPage;
-
-import com.google.common.collect.Iterators;
 
 public final class GoogleCloudStorageFallbacks {
 
@@ -37,16 +31,4 @@ public final class GoogleCloudStorageFallbacks {
          throw propagate(t);
       }
    }
-
-   public static final class EmptyListPageOnNotFoundOr404 implements Fallback<Object> {
-      @Override public ListPage<Object> createOrPropagate(Throwable t) throws Exception {
-         return valOnNotFoundOr404(ListPage.create(null, null, null), t);
-      }
-   }
-
-   public static final class EmptyIteratorOnNotFoundOr404 implements Fallback<Object> {
-      @Override public Iterator<Object> createOrPropagate(Throwable t) throws Exception {
-         return valOnNotFoundOr404(Iterators.emptyIterator(), t);
-      }
-   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageProviderMetadata.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageProviderMetadata.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageProviderMetadata.java
new file mode 100644
index 0000000..1431a5c
--- /dev/null
+++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageProviderMetadata.java
@@ -0,0 +1,72 @@
+/*
+ * 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.googlecloudstorage;
+
+import java.net.URI;
+import java.util.Properties;
+
+import org.jclouds.providers.ProviderMetadata;
+import org.jclouds.providers.internal.BaseProviderMetadata;
+
+import com.google.auto.service.AutoService;
+
+/** Note: This does not set iso3166Codes as Google intentionally does not document them. */
+@AutoService(ProviderMetadata.class)
+public final class GoogleCloudStorageProviderMetadata extends BaseProviderMetadata {
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   @Override
+   public Builder toBuilder() {
+      return builder().fromProviderMetadata(this);
+   }
+
+   public GoogleCloudStorageProviderMetadata() {
+      super(builder());
+   }
+
+   public GoogleCloudStorageProviderMetadata(Builder builder) {
+      super(builder);
+   }
+
+   public static Properties defaultProperties() {
+      return new Properties(); // currently all are set in the api metadata class.
+   }
+
+   public static final class Builder extends BaseProviderMetadata.Builder {
+
+      private Builder() {
+         id("google-cloud-storage") //
+         .name("Google Cloud Storage") //
+         .apiMetadata(new GoogleCloudStorageApiMetadata()) //
+         .homepage(URI.create("https://cloud.google.com/storage")) //
+         .console(URI.create("https://console.developers.google.com/project")) //
+         .defaultProperties(GoogleCloudStorageProviderMetadata.defaultProperties());
+      }
+
+      @Override public GoogleCloudStorageProviderMetadata build() {
+         return new GoogleCloudStorageProviderMetadata(this);
+      }
+
+      @Override public Builder fromProviderMetadata(ProviderMetadata in) {
+         super.fromProviderMetadata(in);
+         return this;
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/GCSBlobStore.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/GCSBlobStore.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/GCSBlobStore.java
index 7140bdf..186fc9b 100644
--- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/GCSBlobStore.java
+++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/GCSBlobStore.java
@@ -43,6 +43,8 @@ import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
 import org.jclouds.blobstore.util.BlobUtils;
 import org.jclouds.collect.Memoized;
 import org.jclouds.domain.Location;
+import org.jclouds.googlecloud.config.CurrentProject;
+import org.jclouds.googlecloud.domain.ListPage;
 import org.jclouds.googlecloudstorage.GoogleCloudStorageApi;
 import org.jclouds.googlecloudstorage.blobstore.functions.BlobMetadataToObjectTemplate;
 import org.jclouds.googlecloudstorage.blobstore.functions.BlobStoreListContainerOptionsToListObjectOptions;
@@ -50,11 +52,10 @@ import org.jclouds.googlecloudstorage.blobstore.functions.BucketToStorageMetadat
 import org.jclouds.googlecloudstorage.blobstore.functions.ObjectListToStorageMetadata;
 import org.jclouds.googlecloudstorage.blobstore.functions.ObjectToBlobMetadata;
 import org.jclouds.googlecloudstorage.blobstore.strategy.internal.MultipartUploadStrategy;
-import org.jclouds.googlecloudstorage.config.UserProject;
 import org.jclouds.googlecloudstorage.domain.Bucket;
 import org.jclouds.googlecloudstorage.domain.DomainResourceReferences;
 import org.jclouds.googlecloudstorage.domain.GCSObject;
-import org.jclouds.googlecloudstorage.domain.ListPage;
+import org.jclouds.googlecloudstorage.domain.ListPageWithPrefixes;
 import org.jclouds.googlecloudstorage.domain.templates.BucketTemplate;
 import org.jclouds.googlecloudstorage.domain.templates.ObjectAccessControlsTemplate;
 import org.jclouds.googlecloudstorage.domain.templates.ObjectTemplate;
@@ -89,7 +90,7 @@ public final class GCSBlobStore extends BaseBlobStore {
             Provider<FetchBlobMetadata> fetchBlobMetadataProvider,
             BlobMetadataToObjectTemplate blobMetadataToObjectTemplate,
             BlobStoreListContainerOptionsToListObjectOptions listContainerOptionsToListObjectOptions,
-            MultipartUploadStrategy multipartUploadStrategy, @UserProject Supplier<String> projectId) {
+            MultipartUploadStrategy multipartUploadStrategy, @CurrentProject Supplier<String> projectId) {
       super(context, blobUtils, defaultLocation, locations);
       this.api = api;
       this.bucketToStorageMetadata = bucketToStorageMetadata;
@@ -152,7 +153,7 @@ public final class GCSBlobStore extends BaseBlobStore {
    /** Returns list of of all the objects */
    @Override
    public PageSet<? extends StorageMetadata> list(String container) {
-      ListPage<GCSObject> gcsList = api.getObjectApi().listObjects(container);
+      ListPageWithPrefixes<GCSObject> gcsList = api.getObjectApi().listObjects(container);
       PageSet<? extends StorageMetadata> list = objectListToStorageMetadata.apply(gcsList);
       return list;
    }
@@ -161,7 +162,7 @@ public final class GCSBlobStore extends BaseBlobStore {
    public PageSet<? extends StorageMetadata> list(String container, ListContainerOptions options) {
       if (options != null && options != ListContainerOptions.NONE) {
          ListObjectOptions listOptions = listContainerOptionsToListObjectOptions.apply(options);
-         ListPage<GCSObject> gcsList = api.getObjectApi().listObjects(container, listOptions);
+         ListPageWithPrefixes<GCSObject> gcsList = api.getObjectApi().listObjects(container, listOptions);
          PageSet<? extends StorageMetadata> list = objectListToStorageMetadata.apply(gcsList);
          return options.isDetailed() ? fetchBlobMetadataProvider.get().setContainerName(container).apply(list) : list;
       } else {
@@ -241,7 +242,7 @@ public final class GCSBlobStore extends BaseBlobStore {
 
    @Override
    protected boolean deleteAndVerifyContainerGone(String container) {
-      ListPage<GCSObject> list = api.getObjectApi().listObjects(container);
+      ListPageWithPrefixes<GCSObject> list = api.getObjectApi().listObjects(container);
       if (list == null) {
          return api.getBucketApi().deleteBucket(container);
       }

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/config/GCSBlobStoreContextModule.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/config/GCSBlobStoreContextModule.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/config/GCSBlobStoreContextModule.java
deleted file mode 100644
index e6fd43f..0000000
--- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/config/GCSBlobStoreContextModule.java
+++ /dev/null
@@ -1,32 +0,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.
- */
-package org.jclouds.googlecloudstorage.blobstore.config;
-
-import com.google.inject.AbstractModule;
-import com.google.inject.Scopes;
-import org.jclouds.blobstore.BlobStore;
-import org.jclouds.blobstore.attr.ConsistencyModel;
-import org.jclouds.googlecloudstorage.blobstore.GCSBlobStore;
-
-public class GCSBlobStoreContextModule extends AbstractModule {
-
-   @Override
-   protected void configure() {
-      bind(ConsistencyModel.class).toInstance(ConsistencyModel.EVENTUAL);
-      bind(BlobStore.class).to(GCSBlobStore.class).in(Scopes.SINGLETON);
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/config/GoogleCloudStorageBlobStoreContextModule.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/config/GoogleCloudStorageBlobStoreContextModule.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/config/GoogleCloudStorageBlobStoreContextModule.java
new file mode 100644
index 0000000..85560e3
--- /dev/null
+++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/config/GoogleCloudStorageBlobStoreContextModule.java
@@ -0,0 +1,33 @@
+/*
+ * 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.googlecloudstorage.blobstore.config;
+
+import org.jclouds.blobstore.BlobStore;
+import org.jclouds.blobstore.attr.ConsistencyModel;
+import org.jclouds.googlecloudstorage.blobstore.GCSBlobStore;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Scopes;
+
+public class GoogleCloudStorageBlobStoreContextModule extends AbstractModule {
+
+   @Override
+   protected void configure() {
+      bind(ConsistencyModel.class).toInstance(ConsistencyModel.EVENTUAL);
+      bind(BlobStore.class).to(GCSBlobStore.class).in(Scopes.SINGLETON);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/ObjectListToStorageMetadata.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/ObjectListToStorageMetadata.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/ObjectListToStorageMetadata.java
index 1fc612d..edc931d 100644
--- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/ObjectListToStorageMetadata.java
+++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/ObjectListToStorageMetadata.java
@@ -27,22 +27,23 @@ import org.jclouds.blobstore.domain.StorageType;
 import org.jclouds.blobstore.domain.internal.PageSetImpl;
 import org.jclouds.blobstore.domain.internal.StorageMetadataImpl;
 import org.jclouds.googlecloudstorage.domain.GCSObject;
-import org.jclouds.googlecloudstorage.domain.ListPage;
+import org.jclouds.googlecloudstorage.domain.ListPageWithPrefixes;
 
 import com.google.common.base.Function;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 
-public class ObjectListToStorageMetadata implements Function<ListPage<GCSObject>, PageSet<? extends StorageMetadata>> {
+public class ObjectListToStorageMetadata
+      implements Function<ListPageWithPrefixes<GCSObject>, PageSet<? extends StorageMetadata>> {
    private final ObjectToBlobMetadata object2blobMd;
 
    @Inject public ObjectListToStorageMetadata(ObjectToBlobMetadata object2blobMd) {
       this.object2blobMd = object2blobMd;
    }
 
-   public PageSet<? extends StorageMetadata> apply(ListPage<GCSObject> from) {
+   public PageSet<? extends StorageMetadata> apply(ListPageWithPrefixes<GCSObject> from) {
       if (from == null) {
-         from = ListPage.create(null, null, null);
+         from = ListPageWithPrefixes.create(null, null, null);
       }
 
       return new PageSetImpl<StorageMetadata>(Iterables.transform(Iterables.transform(from, object2blobMd),

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/MultipartUploadSlicingAlgorithm.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/MultipartUploadSlicingAlgorithm.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/MultipartUploadSlicingAlgorithm.java
index 44c0b8b..dd8c5ab 100644
--- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/MultipartUploadSlicingAlgorithm.java
+++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/MultipartUploadSlicingAlgorithm.java
@@ -16,13 +16,14 @@
  */
 package org.jclouds.googlecloudstorage.blobstore.strategy.internal;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.inject.Inject;
+import javax.annotation.Resource;
+import javax.inject.Named;
+
 import org.jclouds.blobstore.reference.BlobStoreConstants;
 import org.jclouds.logging.Logger;
 
-import javax.annotation.Resource;
-import javax.inject.Named;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.inject.Inject;
 
 public class MultipartUploadSlicingAlgorithm {
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/GoogleCloudStorageHttpApiModule.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/GoogleCloudStorageHttpApiModule.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/GoogleCloudStorageHttpApiModule.java
index db7aba8..862f38f 100644
--- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/GoogleCloudStorageHttpApiModule.java
+++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/GoogleCloudStorageHttpApiModule.java
@@ -16,16 +16,10 @@
  */
 package org.jclouds.googlecloudstorage.config;
 
-import static com.google.common.base.Suppliers.compose;
-import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
-
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
-
-import javax.inject.Named;
 import javax.inject.Singleton;
 
 import org.jclouds.domain.Credentials;
+import org.jclouds.googlecloud.config.CurrentProject;
 import org.jclouds.googlecloudstorage.GoogleCloudStorageApi;
 import org.jclouds.googlecloudstorage.handlers.GoogleCloudStorageErrorHandler;
 import org.jclouds.http.HttpErrorHandler;
@@ -34,15 +28,12 @@ import org.jclouds.http.annotation.Redirection;
 import org.jclouds.http.annotation.ServerError;
 import org.jclouds.location.Provider;
 import org.jclouds.oauth.v2.config.OAuthScopes;
-import org.jclouds.rest.AuthorizationException;
 import org.jclouds.rest.ConfiguresHttpApi;
 import org.jclouds.rest.config.HttpApiModule;
-import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
 
 import com.google.common.base.Function;
-import com.google.common.base.Splitter;
 import com.google.common.base.Supplier;
-import com.google.common.collect.Iterables;
+import com.google.common.base.Suppliers;
 import com.google.inject.Provides;
 
 @ConfiguresHttpApi
@@ -61,25 +52,12 @@ public class GoogleCloudStorageHttpApiModule extends HttpApiModule<GoogleCloudSt
    }
 
    @Provides
-   @Singleton
-   @UserProject
-   public Supplier<String> supplyProject(@Provider final Supplier<Credentials> creds, final GoogleCloudStorageApi api,
-            AtomicReference<AuthorizationException> authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds) {
-      return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException,
-               compose(new Function<Credentials, String>() {
-                  public String apply(Credentials in) {
-                     // ID should be of the form project_id@developer.gserviceaccount.com
-                     // OR (increasingly often) project_id-extended_uid@developer.gserviceaccount.com
-                     String projectName = in.identity;
-                     if (projectName.indexOf("@") != -1) {
-                        projectName = Iterables.get(Splitter.on("@").split(projectName), 0);
-                        if (projectName.indexOf("-") != -1) {
-                           // if ID is of the form project_id-extended_uid@developer.gserviceaccount.com
-                           projectName = Iterables.get(Splitter.on("-").split(projectName), 0);
-                        }
-                     }
-                     return projectName;
-                  }
-               }, creds), seconds, TimeUnit.SECONDS);
+   @Singleton @CurrentProject
+   public Supplier<String> supplyProject(@Provider final Supplier<Credentials> creds) {
+      return Suppliers.compose(new Function<Credentials, String>() {
+         @Override public String apply(Credentials in) {
+            return CurrentProject.ClientEmail.toProjectNumber(in.identity);
+         }
+      }, creds);
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/GoogleCloudStorageParserModule.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/GoogleCloudStorageParserModule.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/GoogleCloudStorageParserModule.java
index 279d497..77933a7 100644
--- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/GoogleCloudStorageParserModule.java
+++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/GoogleCloudStorageParserModule.java
@@ -18,17 +18,21 @@ package org.jclouds.googlecloudstorage.config;
 
 import java.lang.reflect.Type;
 import java.util.Map;
+import java.util.Set;
 
 import javax.inject.Singleton;
 
+import org.jclouds.googlecloud.config.ListPageAdapterFactory;
 import org.jclouds.googlecloudstorage.domain.templates.BucketTemplate;
 import org.jclouds.json.config.GsonModule;
 
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonSerializationContext;
 import com.google.gson.JsonSerializer;
+import com.google.gson.TypeAdapterFactory;
 import com.google.inject.AbstractModule;
 import com.google.inject.Provides;
 
@@ -44,6 +48,11 @@ public class GoogleCloudStorageParserModule extends AbstractModule {
                .build();
    }
 
+   // TODO: change jclouds core to use collaborative set bindings
+   @Provides @Singleton Set<TypeAdapterFactory> typeAdapterFactories() {
+      return ImmutableSet.<TypeAdapterFactory>of(new ListPageAdapterFactory());
+   }
+
    private static class BucketTemplateTypeAdapter implements JsonSerializer<BucketTemplate> {
 
       @Override

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/UserProject.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/UserProject.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/UserProject.java
deleted file mode 100644
index ae59af0..0000000
--- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/UserProject.java
+++ /dev/null
@@ -1,33 +0,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.
- */
-package org.jclouds.googlecloudstorage.config;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import javax.inject.Qualifier;
-
-/**
- * Qualifies a property as the user's project id.
- */
-@Retention(value = RetentionPolicy.RUNTIME)
-@Target(value = {ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
-@Qualifier
-public @interface UserProject {
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/Bucket.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/Bucket.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/Bucket.java
index 1c8e41a..d0f4b33 100644
--- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/Bucket.java
+++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/Bucket.java
@@ -17,7 +17,7 @@
 
 package org.jclouds.googlecloudstorage.domain;
 
-import static org.jclouds.googlecloudstorage.internal.NullSafeCopies.copyOf;
+import static org.jclouds.googlecloud.internal.NullSafeCopies.copyOf;
 
 import java.util.Date;
 import java.util.List;
@@ -151,7 +151,7 @@ public abstract class Bucket {
 
    public abstract List<ObjectAccessControls> defaultObjectAcl();
 
-   public abstract Owner owner();
+   @Nullable public abstract Owner owner();
 
    @Nullable public abstract Location location();
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/GCSObject.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/GCSObject.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/GCSObject.java
index 77c1350..9a38781 100644
--- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/GCSObject.java
+++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/GCSObject.java
@@ -17,7 +17,7 @@
 
 package org.jclouds.googlecloudstorage.domain;
 
-import static org.jclouds.googlecloudstorage.internal.NullSafeCopies.copyOf;
+import static org.jclouds.googlecloud.internal.NullSafeCopies.copyOf;
 
 import java.net.URI;
 import java.util.Date;

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/ListPage.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/ListPage.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/ListPage.java
deleted file mode 100644
index f94b1ca..0000000
--- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/ListPage.java
+++ /dev/null
@@ -1,57 +0,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.
- */
-package org.jclouds.googlecloudstorage.domain;
-
-import static org.jclouds.googlecloudstorage.internal.NullSafeCopies.copyOf;
-
-import java.beans.ConstructorProperties;
-import java.util.List;
-
-import org.jclouds.javax.annotation.Nullable;
-
-import com.google.common.collect.ForwardingList;
-
-/** An immutable list that includes a token, if there is another page available. */
-public final class ListPage<T> extends ForwardingList<T> {
-
-   private final List<T> items;
-   private final String nextPageToken;
-   private final List<String> prefixes;
-
-   public static <T> ListPage<T> create(List<T> items, String nextPageToken, List<String> prefixes) {
-      return new ListPage<T>(items, nextPageToken, prefixes);
-   }
-
-   @ConstructorProperties({ "items", "nextPageToken", "prefixes" })
-   ListPage(List<T> items, String nextPageToken, List<String> prefixes) {
-      this.items = copyOf(items);
-      this.nextPageToken = nextPageToken;
-      this.prefixes = copyOf(prefixes);
-   }
-
-   @Nullable public String nextPageToken() {
-      return nextPageToken;
-   }
-
-   public List<String> prefixes() {
-      return prefixes;
-   }
-
-   @Override protected List<T> delegate() {
-      return items;
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/ListPageWithPrefixes.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/ListPageWithPrefixes.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/ListPageWithPrefixes.java
new file mode 100644
index 0000000..a7eb4cf
--- /dev/null
+++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/ListPageWithPrefixes.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.googlecloudstorage.domain;
+
+import static org.jclouds.googlecloud.internal.NullSafeCopies.copyOf;
+
+import java.beans.ConstructorProperties;
+import java.util.List;
+
+import org.jclouds.googlecloud.domain.ListPage;
+import org.jclouds.javax.annotation.Nullable;
+
+import com.google.common.collect.ForwardingList;
+
+/** An immutable list that includes a token, if there is another page available. */
+public final class ListPageWithPrefixes<T> extends ForwardingList<T> implements ListPage<T> {
+
+   private final List<T> items;
+   private final String nextPageToken;
+   private final List<String> prefixes;
+
+   public static <T> ListPageWithPrefixes<T> create(List<T> items, String nextPageToken, List<String> prefixes) {
+      return new ListPageWithPrefixes<T>(items, nextPageToken, prefixes);
+   }
+
+   @ConstructorProperties({ "items", "nextPageToken", "prefixes" })
+   ListPageWithPrefixes(List<T> items, String nextPageToken, List<String> prefixes) {
+      this.items = copyOf(items);
+      this.nextPageToken = nextPageToken;
+      this.prefixes = copyOf(prefixes);
+   }
+
+   @Override @Nullable public String nextPageToken() {
+      return nextPageToken;
+   }
+
+   public List<String> prefixes() {
+      return prefixes;
+   }
+
+   @Override protected List<T> delegate() {
+      return items;
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/BucketApi.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/BucketApi.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/BucketApi.java
index cdca05c..1328d5c 100644
--- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/BucketApi.java
+++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/BucketApi.java
@@ -33,10 +33,9 @@ import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
 import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.Fallbacks.TrueOnNotFoundOr404;
 import org.jclouds.blobstore.BlobStoreFallbacks.NullOnKeyAlreadyExists;
-import org.jclouds.googlecloudstorage.GoogleCloudStorageFallbacks.EmptyListPageOnNotFoundOr404;
+import org.jclouds.googlecloud.domain.ListPage;
 import org.jclouds.googlecloudstorage.GoogleCloudStorageFallbacks.NullOnBucketAlreadyExists;
 import org.jclouds.googlecloudstorage.domain.Bucket;
-import org.jclouds.googlecloudstorage.domain.ListPage;
 import org.jclouds.googlecloudstorage.domain.templates.BucketTemplate;
 import org.jclouds.googlecloudstorage.options.DeleteBucketOptions;
 import org.jclouds.googlecloudstorage.options.GetBucketOptions;
@@ -185,7 +184,6 @@ public interface BucketApi {
    @GET
    @Produces(APPLICATION_JSON)
    @Path("/b")
-   @Fallback(EmptyListPageOnNotFoundOr404.class)
    ListPage<Bucket> listBucket(@QueryParam("project") String projectId);
 
    /**
@@ -200,7 +198,6 @@ public interface BucketApi {
    @GET
    @Produces(APPLICATION_JSON)
    @Path("/b")
-   @Fallback(EmptyListPageOnNotFoundOr404.class)
    ListPage<Bucket> listBucket(@QueryParam("project") String projectId, ListOptions options);
 
    /**

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/ObjectApi.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/ObjectApi.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/ObjectApi.java
index 00407b5..3d6127e 100644
--- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/ObjectApi.java
+++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/ObjectApi.java
@@ -32,11 +32,10 @@ import javax.ws.rs.Produces;
 import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
 import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.Fallbacks.TrueOnNotFoundOr404;
-import org.jclouds.googlecloudstorage.GoogleCloudStorageFallbacks.EmptyListPageOnNotFoundOr404;
 import org.jclouds.googlecloudstorage.binders.MultipartUploadBinder;
 import org.jclouds.googlecloudstorage.binders.UploadBinder;
 import org.jclouds.googlecloudstorage.domain.GCSObject;
-import org.jclouds.googlecloudstorage.domain.ListPage;
+import org.jclouds.googlecloudstorage.domain.ListPageWithPrefixes;
 import org.jclouds.googlecloudstorage.domain.templates.ComposeObjectTemplate;
 import org.jclouds.googlecloudstorage.domain.templates.ObjectTemplate;
 import org.jclouds.googlecloudstorage.options.ComposeObjectOptions;
@@ -212,7 +211,7 @@ public interface ObjectApi {
     * @param objectName
     *           Name of the object
     * @param options
-    *           Supply {@link DeletObjectOptions} with optional query parameters
+    *           Supply {@link DeleteObjectOptions} with optional query parameters
     */
    @Named("Object:delete")
    @DELETE
@@ -226,15 +225,12 @@ public interface ObjectApi {
     *
     * @param bucketName
     *           Name of the bucket in which to look for objects.
-    *
-    * @return a {@link ListPage<Object>}
     */
    @Named("Object:list")
    @GET
    @Consumes(APPLICATION_JSON)
    @Path("storage/v1/b/{bucket}/o")
-   @Fallback(EmptyListPageOnNotFoundOr404.class)
-   ListPage<GCSObject> listObjects(@PathParam("bucket") String bucketName);
+   ListPageWithPrefixes<GCSObject> listObjects(@PathParam("bucket") String bucketName);
 
    /**
     * Retrieves a list of objects matching the criteria.
@@ -249,8 +245,7 @@ public interface ObjectApi {
    @GET
    @Consumes(APPLICATION_JSON)
    @Path("storage/v1/b/{bucket}/o")
-   @Fallback(EmptyListPageOnNotFoundOr404.class)
-   ListPage<GCSObject> listObjects(@PathParam("bucket") String bucketName, ListObjectOptions options);
+   ListPageWithPrefixes<GCSObject> listObjects(@PathParam("bucket") String bucketName, ListObjectOptions options);
 
    /**
     * Updates an object metadata

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/handlers/GoogleCloudStorageRedirectRetryHandler.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/handlers/GoogleCloudStorageRedirectRetryHandler.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/handlers/GoogleCloudStorageRedirectRetryHandler.java
index 45e6924..b7c236b 100644
--- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/handlers/GoogleCloudStorageRedirectRetryHandler.java
+++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/handlers/GoogleCloudStorageRedirectRetryHandler.java
@@ -22,6 +22,7 @@ import org.jclouds.http.HttpCommand;
 import org.jclouds.http.HttpResponse;
 import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
 import org.jclouds.http.handlers.RedirectionRetryHandler;
+
 import com.google.inject.Inject;
 
 /**

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/internal/NullSafeCopies.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/internal/NullSafeCopies.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/internal/NullSafeCopies.java
deleted file mode 100644
index 3cec1b4..0000000
--- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/internal/NullSafeCopies.java
+++ /dev/null
@@ -1,39 +0,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.
- */
-package org.jclouds.googlecloudstorage.internal;
-
-import java.util.List;
-import java.util.Map;
-
-import org.jclouds.javax.annotation.Nullable;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-
-public class NullSafeCopies {
-
-   public static <K, V> Map<K, V> copyOf(@Nullable Map<K, V> map) {
-      return map != null ? ImmutableMap.copyOf(map) : ImmutableMap.<K, V>of();
-   }
-
-   public static <E> List<E> copyOf(@Nullable List<E> list) {
-      return list != null ? ImmutableList.copyOf(list) : ImmutableList.<E>of();
-   }
-
-   private NullSafeCopies() {
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/options/ListOptions.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/options/ListOptions.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/options/ListOptions.java
index 3966a8c..87aadb9 100644
--- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/options/ListOptions.java
+++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/options/ListOptions.java
@@ -19,18 +19,16 @@ package org.jclouds.googlecloudstorage.options;
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import org.jclouds.googlecloudstorage.domain.DomainResourceReferences.Projection;
-import org.jclouds.http.options.BaseHttpRequestOptions;
 
-public class ListOptions extends BaseHttpRequestOptions {
+public class ListOptions extends org.jclouds.googlecloud.options.ListOptions {
 
    public ListOptions pageToken(String pageToken) {
       this.queryParameters.put("pageToken", checkNotNull(pageToken, "pageToken"));
       return this;
    }
 
-   public ListOptions maxResults(Integer maxResults) {
-      this.queryParameters.put("maxResults", checkNotNull(maxResults, "maxResults") + "");
-      return this;
+   @Override public ListOptions maxResults(Integer maxResults) {
+      return (ListOptions) super.maxResults(maxResults);
    }
 
    public ListOptions projection(Projection projection) {

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/parser/ParseToPayloadEnclosing.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/parser/ParseToPayloadEnclosing.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/parser/ParseToPayloadEnclosing.java
index 8d79e45..8eceede 100644
--- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/parser/ParseToPayloadEnclosing.java
+++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/parser/ParseToPayloadEnclosing.java
@@ -18,6 +18,7 @@ package org.jclouds.googlecloudstorage.parser;
 
 import org.jclouds.http.HttpResponse;
 import org.jclouds.http.internal.PayloadEnclosingImpl;
+
 import com.google.common.base.Function;
 
 public class ParseToPayloadEnclosing implements Function<HttpResponse, PayloadEnclosingImpl> {

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/reference/GoogleCloudStorageConstants.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/reference/GoogleCloudStorageConstants.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/reference/GoogleCloudStorageConstants.java
index b593120..299a249 100644
--- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/reference/GoogleCloudStorageConstants.java
+++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/reference/GoogleCloudStorageConstants.java
@@ -23,8 +23,6 @@ public final class GoogleCloudStorageConstants {
    private GoogleCloudStorageConstants() {
    }
 
-   public static final String GCS_PROVIDER_NAME = "google-cloud-storage";
-
    /**
     * The total time, in msecs, to wait for an operation to complete.
     */

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApiMetadataTest.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApiMetadataTest.java b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApiMetadataTest.java
deleted file mode 100644
index 579bbd1..0000000
--- a/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApiMetadataTest.java
+++ /dev/null
@@ -1,31 +0,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.
- */
-package org.jclouds.googlecloudstorage;
-
-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;
-
-@Test(groups = "unit", testName = "GoogleStorageApiMetadataTest")
-public class GoogleCloudStorageApiMetadataTest extends BaseApiMetadataTest {
-   public GoogleCloudStorageApiMetadataTest() {
-      super(new GoogleCloudStorageApiMetadata(), ImmutableSet.<TypeToken<? extends View>> of());
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/GoogleCloudStorageAuthenticatedRestContextLiveTest.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/GoogleCloudStorageAuthenticatedRestContextLiveTest.java b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/GoogleCloudStorageAuthenticatedRestContextLiveTest.java
deleted file mode 100644
index c1b8636..0000000
--- a/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/GoogleCloudStorageAuthenticatedRestContextLiveTest.java
+++ /dev/null
@@ -1,34 +0,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.
- */
-package org.jclouds.googlecloudstorage;
-
-import org.jclouds.oauth.v2.internal.BaseOAuthAuthenticatedApiLiveTest;
-import org.testng.annotations.Test;
-
-@Test(groups = "live")
-public class GoogleCloudStorageAuthenticatedRestContextLiveTest extends
-         BaseOAuthAuthenticatedApiLiveTest<GoogleCloudStorageApi> {
-
-   public GoogleCloudStorageAuthenticatedRestContextLiveTest() {
-      provider = "google-cloud-storage";
-   }
-
-   @Override
-   public String getScopes() {
-      return "https://www.googleapis.com/auth/devstorage.full_control";
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/GoogleCloudStorageProviderMetadataTest.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/GoogleCloudStorageProviderMetadataTest.java b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/GoogleCloudStorageProviderMetadataTest.java
new file mode 100644
index 0000000..2ddc1c2
--- /dev/null
+++ b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/GoogleCloudStorageProviderMetadataTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.googlecloudstorage;
+
+import org.jclouds.providers.internal.BaseProviderMetadataTest;
+import org.testng.annotations.Test;
+
+/**
+ * Tests that GoogleComputeProviderMetadata is properly registered in ServiceLoader
+ * <p/>
+ * <pre>
+ * META-INF/services/org.jclouds.providers.ProviderMetadata
+ * </pre>
+ */
+@Test(groups = "unit", testName = "GoogleCloudStorageProviderMetadataTest")
+public class GoogleCloudStorageProviderMetadataTest extends BaseProviderMetadataTest {
+   public GoogleCloudStorageProviderMetadataTest() {
+      super(new GoogleCloudStorageProviderMetadata(), new GoogleCloudStorageApiMetadata());
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/blobstore/integration/GCSBlobIntegrationLiveTest.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/blobstore/integration/GCSBlobIntegrationLiveTest.java b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/blobstore/integration/GCSBlobIntegrationLiveTest.java
index 5f622f4..cef46f8 100644
--- a/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/blobstore/integration/GCSBlobIntegrationLiveTest.java
+++ b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/blobstore/integration/GCSBlobIntegrationLiveTest.java
@@ -16,12 +16,12 @@
  */
 package org.jclouds.googlecloudstorage.blobstore.integration;
 
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotEquals;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
-import static org.assertj.core.api.Assertions.assertThat;
 
 import java.io.File;
 import java.io.IOException;
@@ -37,6 +37,7 @@ import org.jclouds.blobstore.domain.PageSet;
 import org.jclouds.blobstore.domain.StorageMetadata;
 import org.jclouds.blobstore.integration.internal.BaseBlobIntegrationTest;
 import org.jclouds.blobstore.options.PutOptions;
+import org.jclouds.googlecloud.internal.TestProperties;
 import org.jclouds.googlecloudstorage.blobstore.strategy.internal.MultipartUpload;
 import org.jclouds.io.Payloads;
 import org.jclouds.io.payloads.ByteSourcePayload;
@@ -58,17 +59,16 @@ public class GCSBlobIntegrationLiveTest extends BaseBlobIntegrationTest {
 
    private long PART_SIZE = MultipartUpload.MIN_PART_SIZE;
 
-   @Override
-   protected Properties setupProperties() {
-      Properties properties = super.setupProperties();
-      properties.put("jclouds.mpu.parts.size", 2 * 1024 * 1024);
-      return properties;
-   }
-
    public GCSBlobIntegrationLiveTest() throws IOException {
       provider = "google-cloud-storage";
    }
 
+   @Override protected Properties setupProperties() {
+      Properties properties = super.setupProperties();
+      properties.put("jclouds.mpu.parts.size", 2 * 1024 * 1024);
+      return TestProperties.apply(provider, properties);
+   }
+
    @Override
    @Test(enabled = false)
    public void testGetTwoRanges() throws SkipException {

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/blobstore/integration/GCSBlobLiveTest.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/blobstore/integration/GCSBlobLiveTest.java b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/blobstore/integration/GCSBlobLiveTest.java
index 50613b6..3db2158 100644
--- a/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/blobstore/integration/GCSBlobLiveTest.java
+++ b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/blobstore/integration/GCSBlobLiveTest.java
@@ -21,10 +21,12 @@ import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 
 import java.io.IOException;
+import java.util.Properties;
 
 import org.jclouds.blobstore.BlobStore;
 import org.jclouds.blobstore.domain.Blob;
 import org.jclouds.blobstore.integration.internal.BaseBlobLiveTest;
+import org.jclouds.googlecloud.internal.TestProperties;
 import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpResponse;
 import org.jclouds.http.internal.PayloadEnclosingImpl;
@@ -50,6 +52,10 @@ public class GCSBlobLiveTest extends BaseBlobLiveTest {
       provider = "google-cloud-storage";
    }
 
+   @Override protected Properties setupProperties() {
+      return TestProperties.apply(provider, super.setupProperties());
+   }
+
    @Override
    @Parameters({ "jclouds.blobstore.httpstream.url", "jclouds.blobstore.httpstream.md5" })
    public void testCopyUrl(String httpStreamUrl, String httpStreamMD5) throws Exception {

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/blobstore/integration/GCSContainerIntegrationLiveTest.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/blobstore/integration/GCSContainerIntegrationLiveTest.java b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/blobstore/integration/GCSContainerIntegrationLiveTest.java
index f4a116b..d3686de 100644
--- a/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/blobstore/integration/GCSContainerIntegrationLiveTest.java
+++ b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/blobstore/integration/GCSContainerIntegrationLiveTest.java
@@ -22,6 +22,7 @@ import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNull;
 
 import java.io.IOException;
+import java.util.Properties;
 
 import javax.ws.rs.core.MediaType;
 
@@ -30,6 +31,7 @@ import org.jclouds.blobstore.domain.PageSet;
 import org.jclouds.blobstore.domain.StorageMetadata;
 import org.jclouds.blobstore.integration.internal.BaseContainerIntegrationTest;
 import org.jclouds.blobstore.options.ListContainerOptions;
+import org.jclouds.googlecloud.internal.TestProperties;
 import org.testng.SkipException;
 import org.testng.annotations.Test;
 
@@ -43,6 +45,10 @@ public class GCSContainerIntegrationLiveTest extends BaseContainerIntegrationTes
       provider = "google-cloud-storage";
    }
 
+   @Override protected Properties setupProperties() {
+      return TestProperties.apply(provider, super.setupProperties());
+   }
+
    @Override
    @Test(groups = { "integration", "live" })
    public void testWithDetails() throws InterruptedException, IOException {
@@ -93,5 +99,4 @@ public class GCSContainerIntegrationLiveTest extends BaseContainerIntegrationTes
       // GCS does not support directories, rather it supports prefixes which look like directories.
       throw new SkipException("directories are not supported in GCS");
    }
-
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/blobstore/integration/GCSContainerLiveTest.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/blobstore/integration/GCSContainerLiveTest.java b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/blobstore/integration/GCSContainerLiveTest.java
index e3fb626..305db36 100644
--- a/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/blobstore/integration/GCSContainerLiveTest.java
+++ b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/blobstore/integration/GCSContainerLiveTest.java
@@ -16,7 +16,10 @@
  */
 package org.jclouds.googlecloudstorage.blobstore.integration;
 
+import java.util.Properties;
+
 import org.jclouds.blobstore.integration.internal.BaseContainerLiveTest;
+import org.jclouds.googlecloud.internal.TestProperties;
 import org.testng.annotations.Test;
 
 @Test(groups = { "live" })
@@ -25,4 +28,8 @@ public class GCSContainerLiveTest extends BaseContainerLiveTest {
    public GCSContainerLiveTest() {
       provider = "google-cloud-storage";
    }
+
+   @Override protected Properties setupProperties() {
+      return TestProperties.apply(provider, super.setupProperties());
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/f191c8fb/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/BucketApiExpectTest.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/BucketApiExpectTest.java b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/BucketApiExpectTest.java
index f71425b..2cfee9b 100644
--- a/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/BucketApiExpectTest.java
+++ b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/BucketApiExpectTest.java
@@ -118,8 +118,9 @@ public class BucketApiExpectTest extends BaseGoogleCloudStorageApiExpectTest {
 
    }
 
-   public void testListBucketResponseIs4xx() throws Exception {
-      HttpResponse listResponse = HttpResponse.builder().statusCode(404).build();
+   @Test(enabled = false)
+   public void listBucketEmpty() throws Exception {
+      HttpResponse listResponse = null; // TODO: get a copy of an empty bucket response
 
       BucketApi api = requestsSendResponses(requestForScopes(STORAGE_READONLY_SCOPE), TOKEN_RESPONSE,
                LIST_BUCKET_REQUEST, listResponse).getBucketApi();