package org.activityinfo.server.endpoint.export;
/*
* #%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.appengine.api.taskqueue.QueueFactory;
import com.google.appengine.api.taskqueue.RetryOptions;
import com.google.appengine.api.taskqueue.TaskOptions;
import com.google.appengine.tools.cloudstorage.GcsFileMetadata;
import com.google.appengine.tools.cloudstorage.GcsFilename;
import com.google.appengine.tools.cloudstorage.GcsService;
import com.google.appengine.tools.cloudstorage.GcsServiceFactory;
import com.google.common.base.Strings;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.activityinfo.model.auth.AuthenticatedUser;
import org.activityinfo.server.command.DispatcherSync;
import org.activityinfo.server.report.output.StorageProvider;
import javax.inject.Provider;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
/**
* Exports complete data to an Excel file
*
* @author Alex Bertram
*/
@Singleton
public class ExportSitesServlet extends HttpServlet {
public static final String X_AI_STORAGE_PROXY = "X-AI-Storage-Proxy";
private DispatcherSync dispatcher;
private StorageProvider storageProvider;
private Provider<AuthenticatedUser> authenticatedUserProvider;
private SecureRandom random = new SecureRandom();
@Inject
public ExportSitesServlet(DispatcherSync dispatcher,
StorageProvider storageProvider,
Provider<AuthenticatedUser> authenticatedUserProvider) {
this.dispatcher = dispatcher;
this.storageProvider = storageProvider;
this.authenticatedUserProvider = authenticatedUserProvider;
}
/**
* Initiates an export to Excel task. A token is send back to the client as plain text
* that can be use to poll the status of the export and retrieve the result.
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// Create a unique key from which the user can retrieve the file from GCS
String exportId = Long.toString(Math.abs(random.nextLong()), 16);
TaskOptions options = TaskOptions.Builder.withUrl(ExportSitesTask.END_POINT);
for(Map.Entry<String, String[]> entry : req.getParameterMap().entrySet()) {
options.param(entry.getKey(), entry.getValue()[0]);
}
options.param("userId", Integer.toString(authenticatedUserProvider.get().getId()));
options.param("userEmail", authenticatedUserProvider.get().getEmail());
options.param("exportId", exportId);
options.param("filename", fileName());
options.retryOptions(RetryOptions.Builder.withTaskRetryLimit(3));
QueueFactory.getDefaultQueue().add(options);
resp.setStatus(HttpServletResponse.SC_ACCEPTED);
resp.getOutputStream().print(exportId);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String exportId = req.getParameter("id");
// First determine whether the file is available
GcsService gcs = GcsServiceFactory.createGcsService();
GcsFilename fileName = new GcsFilename("activityinfo-generated", exportId);
GcsFileMetadata metadata = gcs.getMetadata(fileName);
if(metadata == null) {
resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
} else {
// First determine whether the file is available
GcsAppIdentityServiceUrlSigner signer = new GcsAppIdentityServiceUrlSigner();
String url;
try {
url = signer.getSignedUrl("GET", ExportSitesTask.EXPORT_BUCKET_NAME + "/" + exportId);
} catch (Exception e) {
throw new RuntimeException("Failed to sign url", e);
}
// Workaround for the great embargo of 2014
// This will allow download links through our proxy instead of
// through google's network.
if(!Strings.isNullOrEmpty(req.getHeader(X_AI_STORAGE_PROXY))) {
url = url.replace("https://storage.googleapis.com", "http://" + req.getHeader(X_AI_STORAGE_PROXY));
}
resp.setStatus(HttpServletResponse.SC_OK);
resp.getOutputStream().print(url);
}
}
private String fileName() {
String date = new SimpleDateFormat("YYYY-MM-dd_HHmmss").format(new Date());
return ("ActivityInfo_Export_" + date + ".xls").replace(" ", "_");
}
}