/* (c) 2017 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.rest.catalog;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.io.FilenameUtils;
import org.geoserver.catalog.Catalog;
import org.geoserver.platform.resource.Resource;
import org.geoserver.platform.resource.Resources;
import org.geoserver.rest.RestException;
import org.geoserver.rest.util.RESTUtils;
import org.geotools.util.logging.Logging;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
public abstract class AbstractStoreUploadController extends AbstractCatalogController {
static final Logger LOGGER = Logging.getLogger(AbstractStoreUploadController.class);
/**
* The ways a file upload can be achieved
*/
protected enum UploadMethod {
file(true), external(false), url(true);
boolean inline;
UploadMethod(boolean inline) {
this.inline = inline;
}
public boolean isInline() {
return inline;
}
}
public AbstractStoreUploadController(Catalog catalog) {
super(catalog);
}
/**
*
* @param store
* @param format
* @param directory
*
*/
protected List<Resource> handleFileUpload(String store, String workspace, UploadMethod method,
String format, Resource directory, HttpServletRequest request) {
List<Resource> files = new ArrayList<>();
Resource uploadedFile;
boolean external = false;
try {
if (method == UploadMethod.file) {
// we want to delete the previous dir contents only in case of PUT, not
// in case of POST (harvest, available only for raster data)
boolean cleanPreviousContents = HttpMethod.PUT.name().equals(request.getMethod());
String filename = request.getParameter("filename");
if (filename == null) {
filename = buildUploadedFilename(store, format);
}
uploadedFile = RESTUtils.handleBinUpload(filename, directory, cleanPreviousContents,
request, workspace);
} else if (method == UploadMethod.url) {
uploadedFile = RESTUtils.handleURLUpload(buildUploadedFilename(store, format),
workspace, directory, request);
} else if (method == UploadMethod.external) {
uploadedFile = RESTUtils.handleEXTERNALUpload(request);
external = true;
} else {
throw new RestException("Unrecognized file upload method: " + method,
HttpStatus.BAD_REQUEST);
}
} catch (Throwable t) {
if (t instanceof RestException) {
throw (RestException) t;
} else {
throw new RestException("Error while storing uploaded file:",
HttpStatus.INTERNAL_SERVER_ERROR, t);
}
}
// handle the case that the uploaded file was a zip file, if so unzip it
if (RESTUtils.isZipMediaType(request)) {
// rename to .zip if need be
if (!uploadedFile.name().endsWith(".zip")) {
Resource newUploadedFile = uploadedFile.parent()
.get(FilenameUtils.getBaseName(uploadedFile.path()) + ".zip");
String oldFileName = uploadedFile.name();
if (!uploadedFile.renameTo(newUploadedFile)) {
String errorMessage = "Error renaming zip file from " + oldFileName + " -> "
+ newUploadedFile.name();
throw new RestException(errorMessage, HttpStatus.INTERNAL_SERVER_ERROR);
}
uploadedFile = newUploadedFile;
}
// unzip the file
try {
// Unzipping of the file and, if it is a POST request, filling of the File List
RESTUtils.unzipFile(uploadedFile, directory, workspace, store, request, files,
external);
// look for the "primary" file
// TODO: do a better check
Resource primaryFile = findPrimaryFile(directory, format);
if (primaryFile != null) {
uploadedFile = primaryFile;
} else {
throw new RestException(
"Could not find appropriate " + format + " file in archive",
HttpStatus.BAD_REQUEST);
}
} catch (RestException e) {
throw e;
} catch (Exception e) {
throw new RestException("Error occured unzipping file",
HttpStatus.INTERNAL_SERVER_ERROR, e);
}
}
// If the File List is empty then the uploaded file must be added
if (uploadedFile != null) {
files.clear();
files.add(uploadedFile);
}
return files;
}
/**
* Build name for an uploaded file.
*/
private String buildUploadedFilename(String store, String format) {
if ("h2".equalsIgnoreCase(format)) {
return store + ".data.db";
} else {
return store + "." + format;
}
}
/**
*
* @param directory
* @param format
*
*/
protected Resource findPrimaryFile(Resource directory, String format) {
for (Resource f : Resources.list(directory,
new Resources.ExtensionFilter(format.toUpperCase()), true)) {
// assume the first
return f;
}
return null;
}
}