package org.activityinfo.service.gcs;
/*
* #%L
* ActivityInfo Server
* %%
* Copyright (C) 2009 - 2013 UNICEF
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
import com.google.api.client.googleapis.MethodOverride;
import com.google.api.client.googleapis.media.MediaHttpUploader;
import com.google.api.client.http.*;
import com.google.api.client.http.apache.ApacheHttpTransport;
import com.google.appengine.api.appidentity.AppIdentityService;
import com.google.appengine.api.appidentity.AppIdentityServiceFactory;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.blobstore.BlobstoreServiceFactory;
import com.google.appengine.api.blobstore.UploadOptions;
import com.google.common.collect.ImmutableList;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.activityinfo.service.DeploymentConfiguration;
import java.io.IOException;
import java.util.List;
/**
* @author yuriyz on 8/11/14.
*/
@Singleton
public class GcsUploadService {
public static final String HOST = "https://www.googleapis.com";
public static final String GOOGLE_STORAGE_PREFIX = "/gs/";
public static final List<String> OAUTH_SCOPES =
ImmutableList.of("https://www.googleapis.com/auth/devstorage.read_write");
private final AppIdentityService appIdentityService = AppIdentityServiceFactory.getAppIdentityService();
private final BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
// private final GcsService gcsService = GcsServiceFactory.createGcsService(RetryParams.getDefaultInstance());
private final DeploymentConfiguration config;
private final HttpTransport transport = new ApacheHttpTransport();
private final HttpRequestFactory httpRequestFactory = transport.createRequestFactory();
@Inject
public GcsUploadService(DeploymentConfiguration config) {
this.config = config;
}
public String createUploadUrl(String formClassId,String fieldId, String blobId) throws IOException {
return createUploadUrlViaRestApi(formClassId, fieldId, blobId) ;
}
private String createUploadUrlViaRestApi(String formClassId, String fieldId, String blobId) throws IOException {
String bucketName = config.getBlobServiceBucketName();
GenericUrl initiationRequestUrl = new GenericUrl(HOST + "/upload/storage/v1/b/" + bucketName + "/o");
String mimeType = "image/png"; // todo pass from client
HttpResponse initialResponse = executeUploadInitiation(initiationRequestUrl, mimeType);
return initialResponse.getHeaders().getLocation();
}
/**
* This method sends a POST request with empty content to get the unique upload URL.
*
* @param initiationRequestUrl The request URL where the initiation request will be sent
*/
private HttpResponse executeUploadInitiation(GenericUrl initiationRequestUrl, final String mediaType) throws IOException {
initiationRequestUrl.put("uploadType", "resumable");
String accessToken = appIdentityService.getAccessToken(OAUTH_SCOPES).getAccessToken();
HttpContent content = new EmptyContent() {
@Override
public String getType() {
return mediaType;
}
};
HttpHeaders initiationHeaders = new HttpHeaders();
HttpRequest request = httpRequestFactory.buildRequest("POST", initiationRequestUrl, content);
initiationHeaders.set(MediaHttpUploader.CONTENT_TYPE_HEADER, mediaType);
initiationHeaders.set("Authorization", "Bearer " + accessToken);
request.getHeaders().putAll(initiationHeaders);
HttpResponse response = executeCurrentRequest(request);
return response;
}
private HttpResponse executeCurrentRequest(HttpRequest request) throws IOException {
// enable GZip encoding if necessary
// method override for non-POST verbs
new MethodOverride().intercept(request);
// don't throw an exception so we can let a custom Google exception be thrown
request.setThrowExceptionOnExecuteError(false);
// execute the request
HttpResponse response = request.execute();
return response;
}
private String createUploadUrlViaBlobstoreApi() {
UploadOptions uploadOptions = UploadOptions.Builder.
withGoogleStorageBucketName(config.getBlobServiceBucketName()); // force upload to GCS
return blobstoreService.createUploadUrl("/", uploadOptions); // no success handler
}
}