de.deepamehta.files.provider.UploadedFileProvider Maven / Gradle / Ivy
package de.deepamehta.files.provider;
import de.deepamehta.files.DiskQuotaCheck;
import de.deepamehta.files.FilesPlugin;
import de.deepamehta.files.UploadedFile;
import de.deepamehta.core.Topic;
import de.deepamehta.core.osgi.CoreActivator;
import de.deepamehta.core.service.CoreService;
import de.deepamehta.config.ConfigService;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import java.io.InputStream;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.List;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.Provider;
@Provider
public class UploadedFileProvider implements MessageBodyReader, DiskQuotaCheck {
// ---------------------------------------------------------------------------------------------- Instance Variables
@Context
private HttpServletRequest request;
private Logger logger = Logger.getLogger(getClass().getName());
// -------------------------------------------------------------------------------------------------- Public Methods
// *** MessageBodyReader Implementation ***
@Override
public boolean isReadable(Class> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
// Note: unlike equals() isCompatible() ignores parameters like "charset" in "application/json;charset=UTF-8"
return type == UploadedFile.class && mediaType.isCompatible(MediaType.MULTIPART_FORM_DATA_TYPE);
}
@Override
public UploadedFile readFrom(Class type, Type genericType, Annotation[] annotations,
MediaType mediaType, MultivaluedMap httpHeaders, InputStream entityStream)
throws IOException, WebApplicationException {
try {
return parseMultiPart();
} catch (Exception e) {
throw new RuntimeException("Deserializing an UploadedFile object failed", e);
}
}
// *** DiskQuotaCheck Implementation ***
@Override
public void check(long fileSize) {
CoreService dm4 = CoreActivator.getCoreService();
String username = dm4.getAccessControl().getUsername(request);
if (username == null) {
throw new RuntimeException("User has no disk quota");
}
dm4.fireEvent(FilesPlugin.CHECK_DISK_QUOTA, username, fileSize, diskQuota(username));
}
// ------------------------------------------------------------------------------------------------- Private Methods
private UploadedFile parseMultiPart() {
try {
UploadedFile file = null;
FileItemFactory factory = new DiskFileItemFactory(); // create a factory for disk-based file items
ServletFileUpload upload = new ServletFileUpload(factory); // create a new file upload handler
List items = upload.parseRequest(request); // parse the request
// FIXME: check if we can use a FileUpload low-level method to parse the request body instead of the
// entire request. Advantage: a) no need to inject the HttpServletRequest, b) no double work as the
// request is already parsed by jersey, c) no dependency on servlet-api.
logger.info("### Parsing multipart/form-data request (" + items.size() + " parts)");
for (FileItem item : items) {
String fieldName = item.getFieldName();
if (item.isFormField()) {
logger.info("### field \"" + fieldName + "\" => \"" + item.getString() + "\"");
} else {
if (file != null) {
throw new RuntimeException("Only single file uploads are supported");
}
file = new UploadedFile(item, this);
logger.info("### field \"" + fieldName + "\" => " + file);
}
}
if (file == null) {
throw new RuntimeException("Request does not contain a file part");
}
return file;
} catch (Exception e) {
throw new RuntimeException("Parsing multipart/form-data request failed", e);
}
}
private long diskQuota(String username) {
Topic usernameTopic = CoreActivator.getCoreService().getAccessControl().getUsernameTopic(username);
ConfigService cs = CoreActivator.getService(ConfigService.class);
Topic configTopic = cs.getConfigTopic("dm4.files.disk_quota", usernameTopic.getId());
return 1024 * 1024 * configTopic.getSimpleValue().intValue();
}
}