use of org.structr.api.RetryException in project structr by structr.
the class UploadServlet method doPost.
@Override
protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException {
try {
if (!ServletFileUpload.isMultipartContent(request)) {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
response.getOutputStream().write("ERROR (400): Request does not contain multipart content.\n".getBytes("UTF-8"));
return;
}
} catch (IOException ioex) {
logger.warn("Unable to send response", ioex);
}
SecurityContext securityContext = null;
String redirectUrl = null;
boolean appendUuidOnRedirect = false;
String path = null;
// isolate request authentication in a transaction
try (final Tx tx = StructrApp.getInstance().tx()) {
try {
securityContext = getConfig().getAuthenticator().initializeAndExamineRequest(request, response);
} catch (AuthenticationException ae) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getOutputStream().write("ERROR (401): Invalid user or password.\n".getBytes("UTF-8"));
return;
}
tx.success();
} catch (FrameworkException fex) {
logger.warn("Unable to examine request", fex);
} catch (IOException ioex) {
logger.warn("Unable to send response", ioex);
}
// something went wrong, but we don't know what...
if (securityContext == null) {
logger.warn("No SecurityContext, aborting.");
return;
}
try {
if (securityContext.getUser(false) == null && !Settings.UploadAllowAnonymous.getValue()) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getOutputStream().write("ERROR (401): Anonymous uploads forbidden.\n".getBytes("UTF-8"));
return;
}
// Ensure access mode is frontend
securityContext.setAccessMode(AccessMode.Frontend);
request.setCharacterEncoding("UTF-8");
// Important: Set character encoding before calling response.getWriter() !!, see Servlet Spec 5.4
response.setCharacterEncoding("UTF-8");
// don't continue on redirects
if (response.getStatus() == 302) {
return;
}
final String pathInfo = request.getPathInfo();
String type = null;
if (StringUtils.isNotBlank(pathInfo)) {
type = SchemaHelper.normalizeEntityName(StringUtils.stripStart(pathInfo.trim(), "/"));
}
uploader.setFileSizeMax((long) MEGABYTE * Settings.UploadMaxFileSize.getValue());
uploader.setSizeMax((long) MEGABYTE * Settings.UploadMaxRequestSize.getValue());
response.setContentType("text/html");
FileItemIterator fileItemsIterator = uploader.getItemIterator(request);
final Map<String, Object> params = new HashMap<>();
while (fileItemsIterator.hasNext()) {
final FileItemStream item = fileItemsIterator.next();
if (item.isFormField()) {
final String fieldName = item.getFieldName();
final String fieldValue = IOUtils.toString(item.openStream(), "UTF-8");
if (REDIRECT_AFTER_UPLOAD_PARAMETER.equals(fieldName)) {
redirectUrl = fieldValue;
} else if (APPEND_UUID_ON_REDIRECT_PARAMETER.equals(fieldName)) {
appendUuidOnRedirect = "true".equalsIgnoreCase(fieldValue);
} else if (UPLOAD_FOLDER_PATH_PARAMETER.equals(fieldName)) {
path = fieldValue;
} else {
params.put(fieldName, fieldValue);
}
} else {
try {
final String contentType = item.getContentType();
boolean isImage = (contentType != null && contentType.startsWith("image"));
boolean isVideo = (contentType != null && contentType.startsWith("video"));
// Override type from path info
if (params.containsKey(NodeInterface.type.jsonName())) {
type = (String) params.get(NodeInterface.type.jsonName());
}
Class cls = null;
if (type != null) {
cls = SchemaHelper.getEntityClassForRawType(type);
}
if (cls == null) {
if (isImage) {
cls = Image.class;
} else if (isVideo) {
cls = SchemaHelper.getEntityClassForRawType("VideoFile");
if (cls == null) {
logger.warn("Unable to create entity of type VideoFile, class is not defined.");
}
} else {
cls = File.class;
}
}
if (cls != null) {
type = cls.getSimpleName();
}
final String name = item.getName().replaceAll("\\\\", "/");
File newFile = null;
String uuid = null;
boolean retry = true;
while (retry) {
retry = false;
Folder uploadFolder = null;
final String defaultUploadFolderConfigValue = Settings.DefaultUploadFolder.getValue();
// If a path attribute was sent, create all folders on the fly.
if (path != null) {
uploadFolder = getOrCreateFolderPath(securityContext, path);
} else if (StringUtils.isNotBlank(defaultUploadFolderConfigValue)) {
uploadFolder = getOrCreateFolderPath(SecurityContext.getSuperUserInstance(), defaultUploadFolderConfigValue);
}
try (final Tx tx = StructrApp.getInstance(securityContext).tx()) {
try (final InputStream is = item.openStream()) {
newFile = FileHelper.createFile(securityContext, is, contentType, cls, name, uploadFolder);
AbstractFile.validateAndRenameFileOnce(newFile, securityContext, null);
final PropertyMap changedProperties = new PropertyMap();
changedProperties.putAll(PropertyMap.inputTypeToJavaType(securityContext, cls, params));
// Update type as it could have changed
changedProperties.put(AbstractNode.type, type);
newFile.unlockSystemPropertiesOnce();
newFile.setProperties(securityContext, changedProperties);
uuid = newFile.getUuid();
}
tx.success();
} catch (RetryException rex) {
retry = true;
}
}
// only the actual existing file creates a UUID output
if (newFile != null) {
// upload trigger
newFile.notifyUploadCompletion();
// send redirect to allow form-based file upload without JavaScript..
if (StringUtils.isNotBlank(redirectUrl)) {
if (appendUuidOnRedirect) {
response.sendRedirect(redirectUrl + uuid);
} else {
response.sendRedirect(redirectUrl);
}
} else {
// Just write out the uuids of the new files
response.getWriter().write(uuid);
}
}
} catch (IOException ex) {
logger.warn("Could not upload file", ex);
}
}
}
} catch (Throwable t) {
final String content;
if (t instanceof FrameworkException) {
final FrameworkException fex = (FrameworkException) t;
logger.error(fex.toString());
content = errorPage(fex);
} else {
logger.error("Exception while processing upload request", t);
content = errorPage(t);
}
try {
final ServletOutputStream out = response.getOutputStream();
IOUtils.write(content, out);
} catch (IOException ex) {
logger.error("Could not write to response", ex);
}
}
}
Aggregations