diff --git a/gcloud-java-core/pom.xml b/gcloud-java-core/pom.xml
index 78baf824c080..fa2e1c18972f 100644
--- a/gcloud-java-core/pom.xml
+++ b/gcloud-java-core/pom.xml
@@ -28,13 +28,13 @@
com.google.http-client
google-http-client
- 1.19.0
+ 1.20.0
compile
com.google.oauth-client
google-oauth-client
- 1.19.0
+ 1.20.0
compile
diff --git a/gcloud-java-core/src/main/java/com/google/gcloud/AuthCredentials.java b/gcloud-java-core/src/main/java/com/google/gcloud/AuthCredentials.java
index 839da54e62cf..6cdb737ddd91 100644
--- a/gcloud-java-core/src/main/java/com/google/gcloud/AuthCredentials.java
+++ b/gcloud-java-core/src/main/java/com/google/gcloud/AuthCredentials.java
@@ -62,7 +62,7 @@ private Object readResolve() throws ObjectStreamException {
}
}
- private static class ServiceAccountAuthCredentials extends AuthCredentials {
+ public static class ServiceAccountAuthCredentials extends AuthCredentials {
private static final long serialVersionUID = 8007708734318445901L;
private final String account;
@@ -94,6 +94,14 @@ protected HttpRequestInitializer httpRequestInitializer(
return builder.build();
}
+ public String account() {
+ return account;
+ }
+
+ public PrivateKey privateKey() {
+ return privateKey;
+ }
+
@Override
public int hashCode() {
return Objects.hash(account, privateKey);
@@ -187,7 +195,7 @@ public static AuthCredentials createApplicationDefaults() throws IOException {
return new ApplicationDefaultAuthCredentials();
}
- public static AuthCredentials createFor(String account, PrivateKey privateKey) {
+ public static ServiceAccountAuthCredentials createFor(String account, PrivateKey privateKey) {
return new ServiceAccountAuthCredentials(account, privateKey);
}
diff --git a/gcloud-java-examples/pom.xml b/gcloud-java-examples/pom.xml
index 66d9fc9c93e3..1c0357d63635 100644
--- a/gcloud-java-examples/pom.xml
+++ b/gcloud-java-examples/pom.xml
@@ -21,4 +21,15 @@
${project.version}
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+
+ false
+
+
+
+
diff --git a/gcloud-java-examples/src/main/java/com/google/gcloud/examples/StorageExample.java b/gcloud-java-examples/src/main/java/com/google/gcloud/examples/StorageExample.java
index b0d44c292d2c..ccf2cd6f5b76 100644
--- a/gcloud-java-examples/src/main/java/com/google/gcloud/examples/StorageExample.java
+++ b/gcloud-java-examples/src/main/java/com/google/gcloud/examples/StorageExample.java
@@ -16,6 +16,8 @@
package com.google.gcloud.examples;
+import com.google.gcloud.AuthCredentials;
+import com.google.gcloud.AuthCredentials.ServiceAccountAuthCredentials;
import com.google.gcloud.RetryParams;
import com.google.gcloud.spi.StorageRpc.Tuple;
import com.google.gcloud.storage.BatchRequest;
@@ -27,6 +29,7 @@
import com.google.gcloud.storage.StorageService;
import com.google.gcloud.storage.StorageService.ComposeRequest;
import com.google.gcloud.storage.StorageService.CopyRequest;
+import com.google.gcloud.storage.StorageService.SignUrlOption;
import com.google.gcloud.storage.StorageServiceFactory;
import com.google.gcloud.storage.StorageServiceOptions;
@@ -40,7 +43,14 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
import java.util.Arrays;
+import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
@@ -58,7 +68,8 @@
* -Dexec.args="[] list []| info [ []]|
* download [local_file]| upload []|
* delete +| cp |
- * compose + | update_metadata [key=value]*"}
+ * compose + | update_metadata [key=value]*|
+ * sign_url "}
*
*
*
@@ -75,7 +86,7 @@ private static abstract class StorageAction {
abstract void run(StorageService storage, T request) throws Exception;
- abstract T parse(String... args) throws IllegalArgumentException, IOException;
+ abstract T parse(String... args) throws Exception;
protected String params() {
return "";
@@ -424,7 +435,7 @@ public String params() {
*
* @see Objects: update
*/
- private static class UpdateMetadata extends StorageAction>> {
+ private static class UpdateMetadataAction extends StorageAction>> {
@Override
public void run(StorageService storage, Tuple> tuple)
@@ -467,6 +478,52 @@ public String params() {
}
}
+ /**
+ * This class demonstrates how to sign a url.
+ * URL will be valid for 1 day.
+ *
+ * @see Signed URLs
+ */
+ private static class SignUrlAction extends
+ StorageAction> {
+
+ private static final char[] PASSWORD = "notasecret".toCharArray();
+
+ @Override
+ public void run(StorageService storage, Tuple tuple)
+ throws Exception {
+ run(storage, tuple.x(), tuple.y());
+ }
+
+ private void run(StorageService storage, ServiceAccountAuthCredentials cred, Blob blob)
+ throws IOException {
+ Calendar cal = Calendar.getInstance();
+ cal.add(Calendar.DATE, 1);
+ long expiration = cal.getTimeInMillis() / 1000;
+ System.out.println("Signed URL: " +
+ storage.signUrl(blob, expiration, SignUrlOption.serviceAccount(cred)));
+ }
+
+ @Override
+ Tuple parse(String... args)
+ throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException,
+ UnrecoverableKeyException {
+ if (args.length != 4) {
+ throw new IllegalArgumentException();
+ }
+ KeyStore keystore = KeyStore.getInstance("PKCS12");
+ keystore.load(Files.newInputStream(Paths.get(args[0])), PASSWORD);
+ PrivateKey privateKey = (PrivateKey) keystore.getKey("privatekey", PASSWORD);
+ ServiceAccountAuthCredentials cred = AuthCredentials.createFor(args[1], privateKey);
+ return Tuple.of(cred, Blob.of(args[2], args[3]));
+ }
+
+ @Override
+ public String params() {
+ return " ";
+ }
+ }
+
static {
ACTIONS.put("info", new InfoAction());
ACTIONS.put("delete", new DeleteAction());
@@ -475,7 +532,8 @@ public String params() {
ACTIONS.put("download", new DownloadAction());
ACTIONS.put("cp", new CopyAction());
ACTIONS.put("compose", new ComposeAction());
- ACTIONS.put("update_metadata", new UpdateMetadata());
+ ACTIONS.put("update_metadata", new UpdateMetadataAction());
+ ACTIONS.put("sign_url", new SignUrlAction());
}
public static void printUsage() {
diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/spi/DefaultStorageRpc.java b/gcloud-java-storage/src/main/java/com/google/gcloud/spi/DefaultStorageRpc.java
index e27d837d7173..f63c57e3c784 100644
--- a/gcloud-java-storage/src/main/java/com/google/gcloud/spi/DefaultStorageRpc.java
+++ b/gcloud-java-storage/src/main/java/com/google/gcloud/spi/DefaultStorageRpc.java
@@ -82,9 +82,9 @@ public DefaultStorageRpc(StorageServiceOptions options) {
HttpRequestInitializer initializer = options.httpRequestInitializer();
this.options = options;
storage = new Storage.Builder(transport, new JacksonFactory(), initializer)
+ .setRootUrl(options.host())
.setApplicationName("gcloud-java")
.build();
- // Todo: make sure nulls are being used as Data.asNull()
}
private static StorageServiceException translate(IOException exception) {
diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/spi/StorageRpc.java b/gcloud-java-storage/src/main/java/com/google/gcloud/spi/StorageRpc.java
index ab1e9affbbce..5a99cce69aa5 100644
--- a/gcloud-java-storage/src/main/java/com/google/gcloud/spi/StorageRpc.java
+++ b/gcloud-java-storage/src/main/java/com/google/gcloud/spi/StorageRpc.java
@@ -1 +1 @@
-/*
* Copyright 2015 Google Inc. All Rights Reserved.
*
* Licensed 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 com.google.gcloud.spi;
import com.google.api.services.storage.model.Bucket;
import com.google.api.services.storage.model.StorageObject;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gcloud.storage.StorageServiceException;
import java.util.List;
import java.util.Map;
public interface StorageRpc {
enum Option {
PREDEFINED_ACL("predefinedAcl"),
PREDEFINED_DEFAULT_OBJECT_ACL("predefinedDefaultObjectAcl"),
IF_METAGENERATION_MATCH("ifMetagenerationMatch"),
IF_METAGENERATION_NOT_MATCH("ifMetagenerationNotMatch"),
IF_GENERATION_NOT_MATCH("ifGenerationMatch"),
IF_GENERATION_MATCH("ifGenerationNotMatch"),
IF_SOURCE_METAGENERATION_MATCH("ifSourceMetagenerationMatch"),
IF_SOURCE_METAGENERATION_NOT_MATCH("ifSourceMetagenerationNotMatch"),
IF_SOURCE_GENERATION_MATCH("ifSourceGenerationMatch"),
IF_SOURCE_GENERATION_NOT_MATCH("ifSourceGenerationNotMatch"),
PREFIX("prefix"),
MAX_RESULTS("maxResults"),
PAGE_TOKEN("pageToken"),
DELIMITER("delimiter"),
VERSIONS("versions");
private final String value;
Option(String value) {
this.value = value;
}
public String value() {
return value;
}
@SuppressWarnings("unchecked")
T get(Map