/*
- * Copyright 2008, 2009 Electronic Business Systems Ltd.
+ * Copyright 2008, 2009, 2010 Electronic Business Systems Ltd.
*
* This file is part of GSS.
*
*/
package gr.ebs.gss.server.rest;
+import static gr.ebs.gss.server.configuration.GSSConfigurationFactory.getConfiguration;
import gr.ebs.gss.client.exceptions.DuplicateNameException;
import gr.ebs.gss.client.exceptions.GSSIOException;
import gr.ebs.gss.client.exceptions.InsufficientPermissionsException;
import gr.ebs.gss.client.exceptions.ObjectNotFoundException;
import gr.ebs.gss.client.exceptions.QuotaExceededException;
import gr.ebs.gss.client.exceptions.RpcException;
+import gr.ebs.gss.server.Login;
+import gr.ebs.gss.server.domain.FileBody;
+import gr.ebs.gss.server.domain.FileHeader;
import gr.ebs.gss.server.domain.FileUploadStatus;
+import gr.ebs.gss.server.domain.Folder;
+import gr.ebs.gss.server.domain.Group;
+import gr.ebs.gss.server.domain.Permission;
import gr.ebs.gss.server.domain.User;
-import gr.ebs.gss.server.domain.dto.FileBodyDTO;
-import gr.ebs.gss.server.domain.dto.FileHeaderDTO;
-import gr.ebs.gss.server.domain.dto.FolderDTO;
-import gr.ebs.gss.server.domain.dto.GroupDTO;
-import gr.ebs.gss.server.domain.dto.PermissionDTO;
import gr.ebs.gss.server.ejb.ExternalAPI;
+import gr.ebs.gss.server.ejb.TransactionHelper;
import gr.ebs.gss.server.webdav.Range;
+import gr.ebs.gss.server.webdav.RequestUtil;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
+import java.util.concurrent.Callable;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
+import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.codec.binary.Base64;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileUploadException;
private ServletContext context;
/**
+ * The style sheet for displaying the directory listings.
+ */
+ private static final String GSS_CSS = "H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} " + "H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} " + "H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} " + "BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} " + "B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} " + "P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}" + "A {color : black;}" + "A.name {color : black;}" + "HR {color : #525D76;}";
+
+
+ /**
* @param servletContext
*/
public FilesHandler(ServletContext servletContext) {
context = servletContext;
}
+ private void updateAccounting(final User user, final Date date, final long bandwidthDiff) {
+ try {
+ new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ getService().updateAccounting(user, date, bandwidthDiff);
+ return null;
+ }
+ });
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ // updateAccounting() doesn't throw any checked exceptions
+ assert false;
+ }
+ }
+
/**
* Serve the specified resource, optionally including the data content.
*
User user = getUser(req);
User owner = getOwner(req);
- if (user == null) user = owner;
boolean exists = true;
Object resource = null;
- FileHeaderDTO file = null;
- FolderDTO folder = null;
+ FileHeader file = null;
+ Folder folder = null;
try {
resource = getService().getResourceAtPath(owner.getId(), path, false);
} catch (ObjectNotFoundException e) {
return;
}
- if (!exists) {
- if (authDeferred) {
- // We do not want to leak information if the request
- // was not authenticated.
- resp.sendError(HttpServletResponse.SC_FORBIDDEN);
- return;
- }
- // A request for upload progress.
- if (progress != null && content) {
- serveProgress(req, resp, progress, user, null);
- return;
- }
-
- resp.sendError(HttpServletResponse.SC_NOT_FOUND, req.getRequestURI());
+ if (!exists && authDeferred) {
+ // We do not want to leak information if the request
+ // was not authenticated.
+ resp.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
- if (resource instanceof FolderDTO)
- folder = (FolderDTO) resource;
+ if (resource instanceof Folder)
+ folder = (Folder) resource;
else
- file = (FileHeaderDTO) resource;
+ file = (FileHeader) resource; // Note that file will be null, if (!exists).
// Now it's time to perform the deferred authentication check.
// Since regular signature checking was already performed,
// we need to check the read-all flag or the signature-in-parameters.
- if (authDeferred)
+ if (authDeferred) {
if (file != null && !file.isReadForAll() && content) {
// Check for GET with the signature in the request parameters.
String auth = req.getParameter(AUTHORIZATION_PARAMETER);
String dateParam = req.getParameter(DATE_PARAMETER);
if (auth == null || dateParam == null) {
- resp.sendError(HttpServletResponse.SC_FORBIDDEN);
- return;
- }
+ // Check for a valid authentication cookie.
+ if (req.getCookies() != null) {
+ boolean found = false;
+ for (Cookie cookie : req.getCookies())
+ if (Login.AUTH_COOKIE.equals(cookie.getName())) {
+ String cookieauth = cookie.getValue();
+ int sepIndex = cookieauth.indexOf(Login.COOKIE_SEPARATOR);
+ if (sepIndex == -1) {
+ handleAuthFailure(req, resp);
+ return;
+ }
+ String username = URLDecoder.decode(cookieauth.substring(0, sepIndex), "US-ASCII");
+ user = null;
+ try {
+ user = getService().findUser(username);
+ } catch (RpcException e) {
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
+ return;
+ }
+ if (user == null) {
+ resp.sendError(HttpServletResponse.SC_FORBIDDEN);
+ return;
+ }
+ req.setAttribute(USER_ATTRIBUTE, user);
+ String token = cookieauth.substring(sepIndex + 1);
+ if (user.getAuthToken() == null) {
+ resp.sendError(HttpServletResponse.SC_FORBIDDEN);
+ return;
+ }
+ if (!Arrays.equals(user.getAuthToken(), Base64.decodeBase64(token))) {
+ resp.sendError(HttpServletResponse.SC_FORBIDDEN);
+ return;
+ }
+ found = true;
+ break;
+ }
+ if (!found) {
+ handleAuthFailure(req, resp);
+ return;
+ }
+ } else {
+ handleAuthFailure(req, resp);
+ return;
+ }
+ } else {
+ long timestamp;
+ try {
+ timestamp = DateUtil.parseDate(dateParam).getTime();
+ } catch (DateParseException e) {
+ resp.sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage());
+ return;
+ }
+ if (!isTimeValid(timestamp)) {
+ resp.sendError(HttpServletResponse.SC_FORBIDDEN);
+ return;
+ }
- long timestamp;
- try {
- timestamp = DateUtil.parseDate(dateParam).getTime();
- } catch (DateParseException e) {
- resp.sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage());
- return;
- }
- if (!isTimeValid(timestamp)) {
- resp.sendError(HttpServletResponse.SC_FORBIDDEN);
- return;
- }
-
- // Fetch the Authorization parameter and find the user specified in it.
- String[] authParts = auth.split(" ");
- if (authParts.length != 2) {
- resp.sendError(HttpServletResponse.SC_FORBIDDEN);
- return;
- }
- String username = authParts[0];
- String signature = authParts[1];
- user = null;
- try {
- user = getService().findUser(username);
- } catch (RpcException e) {
- resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
- return;
+ // Fetch the Authorization parameter and find the user specified in it.
+ String[] authParts = auth.split(" ");
+ if (authParts.length != 2) {
+ resp.sendError(HttpServletResponse.SC_FORBIDDEN);
+ return;
+ }
+ String username = authParts[0];
+ String signature = authParts[1];
+ user = null;
+ try {
+ user = getService().findUser(username);
+ } catch (RpcException e) {
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
+ return;
+ }
+ if (user == null) {
+ resp.sendError(HttpServletResponse.SC_FORBIDDEN);
+ return;
+ }
+ req.setAttribute(USER_ATTRIBUTE, user);
+
+ // Remove the servlet path from the request URI.
+ String p = req.getRequestURI();
+ String servletPath = req.getContextPath() + req.getServletPath();
+ p = p.substring(servletPath.length());
+ // Validate the signature in the Authorization parameter.
+ String data = req.getMethod() + dateParam + p;
+ if (!isSignatureValid(signature, user, data)) {
+ resp.sendError(HttpServletResponse.SC_FORBIDDEN);
+ return;
+ }
}
- if (user == null) {
- resp.sendError(HttpServletResponse.SC_FORBIDDEN);
- return;
- }
+ }
+ else if(folder != null && folder.isReadForAll() || file != null && file.isReadForAll()){
+ //This case refers to a folder or file with public privileges
+ //For a read-for-all folder request, pretend the owner is making it.
+ user = owner;
req.setAttribute(USER_ATTRIBUTE, user);
-
- // Remove the servlet path from the request URI.
- String p = req.getRequestURI();
- String servletPath = req.getContextPath() + req.getServletPath();
- p = p.substring(servletPath.length());
- // Validate the signature in the Authorization parameter.
- String data = req.getMethod() + dateParam + p;
- if (!isSignatureValid(signature, user, data)) {
- resp.sendError(HttpServletResponse.SC_FORBIDDEN);
- return;
- }
- } else if (file != null && !file.isReadForAll() || file == null) {
- // Check for a read-for-all file request.
+ }else if(folder != null && !folder.isReadForAll()){
resp.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
-
+ else{
+ resp.sendError(HttpServletResponse.SC_FORBIDDEN);
+ return;
+ }
+ }
// If the resource is not a collection, and the resource path
// ends with "/" or "\", return NOT FOUND.
if (folder == null)
// A request for upload progress.
if (progress != null && content) {
- if (file == null) {
- resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
- return;
- }
serveProgress(req, resp, progress, user, file);
return;
}
// Fetch the version to retrieve, if specified.
String verStr = req.getParameter(VERSION_PARAM);
int version = 0;
- FileBodyDTO oldBody = null;
+ FileBody oldBody = null;
if (verStr != null && file != null)
try {
version = Integer.valueOf(verStr);
// satisfied. Doing this for folders would require recursive checking
// for all of their children, which in turn would defy the purpose of
// the optimization.
- if (folder == null)
+ if (folder == null){
// Checking If headers.
if (!checkIfHeaders(req, resp, file, oldBody))
return;
+ }
+ else if(!checkIfModifiedSince(req, resp, folder))
+ return;
// Find content type.
String contentType = null;
+ boolean isContentHtml = false;
+ boolean expectJSON = false;
+
if (file != null) {
- contentType = version>0 ? oldBody.getMimeType() : file.getMimeType();
+ contentType = version>0 ? oldBody.getMimeType() : file.getCurrentBody().getMimeType();
if (contentType == null) {
contentType = context.getMimeType(file.getName());
- file.setMimeType(contentType);
+ file.getCurrentBody().setMimeType(contentType);
}
- } else
- contentType = "application/json;charset=UTF-8";
+ } else { // folder != null
+ String accept = req.getHeader("Accept");
+ // The order in this conditional pessimizes the common API case,
+ // but is important for backwards compatibility with existing
+ // clients who send no accept header and expect a JSON response.
+ if (accept != null && accept.contains("text/html")) {
+ contentType = "text/html;charset=UTF-8";
+ isContentHtml = true;
+ //this is the case when clients send the appropriate headers, the contentType is "text/html"
+ //and expect a JSON response. The above check applies to FireGSS client
+ expectJSON = !authDeferred ? true : false;
+ }
+ else {
+ contentType = "application/json;charset=UTF-8";
+ expectJSON = true;
+ }
+ }
+
ArrayList ranges = null;
long contentLength = -1L;
return;
}
// Get content length.
- contentLength = version>0 ? oldBody.getFileSize() : file.getFileSize();
+ contentLength = version>0 ? oldBody.getFileSize() : file.getCurrentBody().getFileSize();
// Special case for zero length files, which would cause a
// (silent) ISE when setting the output buffer size.
if (contentLength == 0L)
else
throw e;
}
-
- if (folder != null
- || (ranges == null || ranges.isEmpty())
- && req.getHeader("Range") == null
- || ranges == FULL) {
+ if (folder != null || (ranges == null || ranges.isEmpty()) && req.getHeader("Range") == null || ranges == FULL) {
// Set the appropriate output headers
if (contentType != null) {
if (logger.isDebugEnabled())
logger.debug("contentLength=" + contentLength);
if (contentLength < Integer.MAX_VALUE)
resp.setContentLength((int) contentLength);
+
else
// Set the content-length as String to be able to use a long
resp.setHeader("content-length", "" + contentLength);
}
InputStream renderResult = null;
- if (folder != null)
- if (content)
- // Serve the directory browser
+ String relativePath = getRelativePath(req);
+ String contextPath = req.getContextPath();
+ String servletPath = req.getServletPath();
+ String contextServletPath = contextPath + servletPath;
+ if (folder != null && content)
+ // Serve the directory browser for a public folder
+ if (isContentHtml && !expectJSON)
+ renderResult = renderHtml(contextServletPath, relativePath, folder,user);
+ // Serve the directory for an ordinary folder or for fireGSS client
+ else
try {
- renderResult = renderJson(user, folder);
- } catch (InsufficientPermissionsException e) {
- resp.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
- return;
- }
+ renderResult = renderJson(user, folder);
+ } catch (InsufficientPermissionsException e) {
+ resp.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
+ return;
+ }
+
+
// Copy the input stream to our output stream (if requested)
if (content) {
try {
// Silent catch
}
try {
- if(file != null && needsContentDisposition(req))
- resp.setHeader("Content-Disposition","attachment; filename=\""+file.getName()+"\"");
+ if(file != null)
+ if (needsContentDisposition(req))
+ resp.setHeader("Content-Disposition","attachment; filename*=UTF-8''"+getDispositionFilename(file));
+ else
+ resp.setHeader("Content-Disposition","inline; filename*=UTF-8''"+getDispositionFilename(file));
if (ostream != null)
copy(file, renderResult, ostream, req, oldBody);
else
copy(file, renderResult, writer, req, oldBody);
- if (file!=null) getService().updateAccounting(user, new Date(), contentLength);
+ if (file!=null) updateAccounting(owner, new Date(), contentLength);
} catch (ObjectNotFoundException e) {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
} catch (RpcException e) {
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
- }
+ }
}
} else {
if (ranges == null || ranges.isEmpty())
copy(file, ostream, range, req, oldBody);
else
copy(file, writer, range, req, oldBody);
- getService().updateAccounting(user, new Date(), contentLength);
+ updateAccounting(owner, new Date(), contentLength);
} catch (ObjectNotFoundException e) {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
copy(file, ostream, ranges.iterator(), contentType, req, oldBody);
else
copy(file, writer, ranges.iterator(), contentType, req, oldBody);
- getService().updateAccounting(user, new Date(), contentLength);
+ updateAccounting(owner, new Date(), contentLength);
} catch (ObjectNotFoundException e) {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
/**
+ * Handles an authentication failure. If no Authorization or Date request
+ * parameters and no Authorization, Date or X-GSS-Date headers were present,
+ * this is a browser request, so redirect to login and then let the user get
+ * back to the file. Otherwise it's a bogus client request and Forbidden is
+ * returned.
+ */
+ private void handleAuthFailure(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ if (req.getParameter(AUTHORIZATION_PARAMETER) == null &&
+ req.getParameter(DATE_PARAMETER) == null &&
+ req.getHeader(AUTHORIZATION_HEADER) == null &&
+ req.getDateHeader(DATE_HEADER) == -1 &&
+ req.getDateHeader(GSS_DATE_HEADER) == -1)
+ resp.sendRedirect(getConfiguration().getString("loginUrl") +
+ "?next=" + req.getRequestURL().toString());
+ else
+ resp.sendError(HttpServletResponse.SC_FORBIDDEN);
+ }
+
+ /**
+ * Return the filename of the specified file properly formatted for
+ * including in the Content-Disposition header.
+ */
+ private String getDispositionFilename(FileHeader file) throws UnsupportedEncodingException {
+ return URLEncoder.encode(file.getName(),"UTF-8").replaceAll("\\+", "%20");
+ }
+
+ /**
* Determines whether the user agent needs the Content-Disposition
* header to be set, in order to properly download a file.
*
* @return true if the Content-Disposition HTTP header must be set
*/
private boolean needsContentDisposition(HttpServletRequest req) {
- String agent = req.getHeader("user-agent");
+ /*String agent = req.getHeader("user-agent");
if (agent != null && agent.contains("MSIE"))
+ return true;*/
+ String dl = req.getParameter("dl");
+ if ("1".equals(dl))
return true;
return false;
}
* @throws IOException if an I/O error occurs
*/
private void serveProgress(HttpServletRequest req, HttpServletResponse resp,
- String parameter, User user, FileHeaderDTO file) throws IOException {
+ String parameter, User user, FileHeader file) throws IOException {
String filename = file == null ? parameter : file.getName();
try {
FileUploadStatus status = getService().getFileUploadStatus(user.getId(), filename);
}
String newName = req.getParameter(NEW_FOLDER_PARAMETER);
+
boolean hasUpdateParam = req.getParameterMap().containsKey(RESOURCE_UPDATE_PARAMETER);
boolean hasTrashParam = req.getParameterMap().containsKey(RESOURCE_TRASH_PARAMETER);
boolean hasRestoreParam = req.getParameterMap().containsKey(RESOURCE_RESTORE_PARAMETER);
String moveTo = req.getParameter(RESOURCE_MOVE_PARAMETER);
String restoreVersion = req.getParameter(RESTORE_VERSION_PARAMETER);
- if (newName != null)
+ if (newName != null){
+ if (!isValidResourceName(newName)) {
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
createFolder(req, resp, path, newName);
+ }
else if (hasUpdateParam)
updateResource(req, resp, path);
else if (hasTrashParam)
else if (restoreVersion != null)
restoreVersion(req, resp, path, restoreVersion);
else
- resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ // IE with Gears uses POST for multiple uploads.
+ putResource(req, resp);
}
/**
* @throws IOException if an I/O error occurs
*/
private void restoreVersion(HttpServletRequest req, HttpServletResponse resp, String path, String version) throws IOException {
- User user = getUser(req);
+ final User user = getUser(req);
User owner = getOwner(req);
Object resource = null;
try {
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
return;
}
- if (resource instanceof FolderDTO) {
+ if (resource instanceof Folder) {
resp.sendError(HttpServletResponse.SC_CONFLICT);
return;
}
try {
- FileHeaderDTO file = (FileHeaderDTO) resource;
- int oldVersion = Integer.parseInt(version);
- getService().restoreVersion(user.getId(), file.getId(), oldVersion);
+ final FileHeader file = (FileHeader) resource;
+ final int oldVersion = Integer.parseInt(version);
+
+ new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ getService().restoreVersion(user.getId(), file.getId(), oldVersion);
+ return null;
+ }
+ });
} catch (InsufficientPermissionsException e) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
} catch (ObjectNotFoundException e) {
resp.sendError(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE, e.getMessage());
} catch (NumberFormatException e) {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
+ } catch (Exception e) {
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
}
}
User owner = getOwner(request);
boolean exists = true;
Object resource = null;
- FileHeaderDTO file = null;
+ FileHeader file = null;
try {
resource = getService().getResourceAtPath(owner.getId(), path, false);
} catch (ObjectNotFoundException e) {
}
if (exists)
- if (resource instanceof FileHeaderDTO) {
- file = (FileHeaderDTO) resource;
+ if (resource instanceof FileHeader) {
+ file = (FileHeader) resource;
if (file.isDeleted()) {
response.sendError(HttpServletResponse.SC_CONFLICT, file.getName() + " is in the trash");
return;
return;
}
- FolderDTO folder = null;
Object parent;
String parentPath = null;
try {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
return;
}
- if (!(parent instanceof FolderDTO)) {
+ if (!(parent instanceof Folder)) {
response.sendError(HttpServletResponse.SC_CONFLICT);
return;
}
- folder = (FolderDTO) parent;
- String fileName = getLastElement(path);
+ final Folder folderLocal = (Folder) parent;
+ final String fileName = getLastElement(path);
+
+ if (!isValidResourceName(fileName)) {
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
FileItemIterator iter;
File uploadedFile = null;
progressListener.setUserId(user.getId());
progressListener.setFilename(fileName);
- String contentType = item.getContentType();
+ final String contentType = item.getContentType();
try {
uploadedFile = getService().uploadFile(stream, user.getId());
} catch (IOException ex) {
throw new GSSIOException(ex, false);
}
- FileHeaderDTO fileDTO = null;
+ FileHeader fileLocal = null;
+ final File upf = uploadedFile;
+ final FileHeader f = file;
+ final User u = user;
if (file == null)
- fileDTO = getService().createFile(user.getId(), folder.getId(), fileName, contentType, uploadedFile);
+ fileLocal = new TransactionHelper<FileHeader>().tryExecute(new Callable<FileHeader>() {
+ @Override
+ public FileHeader call() throws Exception {
+ return getService().createFile(u.getId(), folderLocal.getId(), fileName, contentType, upf.getCanonicalFile().length(), upf.getAbsolutePath());
+ }
+ });
else
- fileDTO = getService().updateFileContents(user.getId(), file.getId(), contentType, uploadedFile);
- getService().updateAccounting(user, new Date(), fileDTO.getFileSize());
+ fileLocal = new TransactionHelper<FileHeader>().tryExecute(new Callable<FileHeader>() {
+ @Override
+ public FileHeader call() throws Exception {
+ return getService().updateFileContents(u.getId(), f.getId(), contentType, upf.getCanonicalFile().length(), upf.getAbsolutePath());
+ }
+ });
+ updateAccounting(owner, new Date(), fileLocal.getCurrentBody().getFileSize());
getService().removeFileUploadProgress(user.getId(), fileName);
}
}
String error = "An error occurred while communicating with the service";
logger.error(error, e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, error);
+ } catch (Exception e) {
+ if (uploadedFile != null && uploadedFile.exists())
+ uploadedFile.delete();
+ String error = "An internal server error occurred";
+ logger.error(error, e);
+ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, error);
}
}
- private String getBackupFilename(FileHeaderDTO file, String filename){
- List<FileHeaderDTO> deletedFiles = new ArrayList<FileHeaderDTO>();
- try{
- deletedFiles = getService().getDeletedFiles(file.getOwner().getId());
- }
- catch(ObjectNotFoundException e){
-
- } catch (RpcException e) {
-
- }
- List<FileHeaderDTO> filesInSameFolder = new ArrayList<FileHeaderDTO>();
- for(FileHeaderDTO deleted : deletedFiles)
- if(deleted.getFolder().getId().equals(file.getFolder().getId()))
- filesInSameFolder.add(deleted);
- int i=1;
- String filenameToCheck = filename;
- for(FileHeaderDTO same : filesInSameFolder)
- if(same.getName().startsWith(filename)){
- String toCheck=same.getName().substring(filename.length(),same.getName().length());
- if(toCheck.startsWith(" ")){
- int test =-1;
- try{
- test = Integer.valueOf(toCheck.replace(" ",""));
- }
- catch(NumberFormatException e){
- //do nothing since string is not a number
- }
- if(test>=i)
- i = test+1;
- }
- }
-
- return filename+" "+i;
- }
-
/**
* Move the resource in the specified path to the specified destination.
*
* @throws IOException if an input/output error occurs
*/
private void moveResource(HttpServletRequest req, HttpServletResponse resp, String path, String moveTo) throws IOException {
- User user = getUser(req);
+ final User user = getUser(req);
User owner = getOwner(req);
Object resource = null;
try {
}
try {
- if (resource instanceof FolderDTO) {
- FolderDTO folder = (FolderDTO) resource;
- getService().moveFolderToPath(user.getId(), destOwner.getId(), folder.getId(), destination);
+ final User dOwner = destOwner;
+ final String dest = destination;
+ if (resource instanceof Folder) {
+ final Folder folderLocal = (Folder) resource;
+ new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ getService().moveFolderToPath(user.getId(), dOwner.getId(), folderLocal.getId(), dest);
+ return null;
+ }
+ });
} else {
- FileHeaderDTO file = (FileHeaderDTO) resource;
- getService().moveFileToPath(user.getId(), destOwner.getId(), file.getId(), destination);
+ final FileHeader fileLocal = (FileHeader) resource;
+ new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ getService().moveFileToPath(user.getId(), dOwner.getId(), fileLocal.getId(), dest);
+ return null;
+ }
+ });
+
}
} catch (InsufficientPermissionsException e) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
} catch (QuotaExceededException e) {
resp.sendError(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE, e.getMessage());
+ } catch (Exception e) {
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, destination);
}
}
* @throws IOException if an input/output error occurs
*/
private void copyResource(HttpServletRequest req, HttpServletResponse resp, String path, String copyTo) throws IOException {
- User user = getUser(req);
+ final User user = getUser(req);
User owner = getOwner(req);
Object resource = null;
try {
User destOwner = null;
boolean exists = true;
try {
- destination = getDestinationPath(req, encodePath(copyTo));
- destination = URLDecoder.decode(destination, "UTF-8");
+ String destinationEncoded = getDestinationPath(req, encodePath(copyTo));
+ destination = URLDecoder.decode(destinationEncoded, "UTF-8");
destOwner = getDestinationOwner(req);
- getService().getResourceAtPath(destOwner.getId(), destination, true);
+ getService().getResourceAtPath(destOwner.getId(), destinationEncoded, true);
} catch (ObjectNotFoundException e) {
exists = false;
} catch (URISyntaxException e) {
}
try {
- if (resource instanceof FolderDTO) {
- FolderDTO folder = (FolderDTO) resource;
- getService().copyFolderStructureToPath(user.getId(), destOwner.getId(), folder.getId(), destination);
+ final User dOwner = destOwner;
+ final String dest = destination;
+ if (resource instanceof Folder) {
+ final Folder folderLocal = (Folder) resource;
+ new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ getService().copyFolderStructureToPath(user.getId(), dOwner.getId(), folderLocal.getId(), dest);
+ return null;
+ }
+ });
} else {
- FileHeaderDTO file = (FileHeaderDTO) resource;
- getService().copyFileToPath(user.getId(), destOwner.getId(), file.getId(), destination);
+ final FileHeader fileLocal = (FileHeader) resource;
+ new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ getService().copyFileToPath(user.getId(), dOwner.getId(), fileLocal.getId(), dest);
+ return null;
+ }
+ });
}
} catch (InsufficientPermissionsException e) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
} catch (QuotaExceededException e) {
resp.sendError(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE, e.getMessage());
+ } catch (Exception e) {
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, destination);
}
}
/**
* A helper method that extracts the relative resource path,
* after removing the 'files' namespace.
+ * The path returned is <i>not</i> URL-decoded.
*
* @param req the HTTP request
* @param path the specified path
* @throws URISyntaxException
* @throws RpcException in case an error occurs while communicating
* with the backend
+ * @throws UnsupportedEncodingException
*/
- private String getDestinationPath(HttpServletRequest req, String path) throws URISyntaxException, RpcException {
+ private String getDestinationPath(HttpServletRequest req, String path) throws URISyntaxException, RpcException, UnsupportedEncodingException {
URI uri = new URI(path);
- String dest = uri.getPath();
+ String dest = uri.getRawPath();
// Remove the context path from the destination URI.
String contextPath = req.getContextPath();
if (!dest.startsWith(contextPath))
int slash = dest.substring(1).indexOf('/');
if (slash == -1)
throw new URISyntaxException(dest, "No username in the destination URI");
- String owner = dest.substring(1, slash + 1);
+ // Decode the user to get the proper characters (mainly the @)
+ String owner = URLDecoder.decode(dest.substring(1, slash + 1), "UTF-8");
User o;
o = getService().findUser(owner);
if (o == null)
* @throws IOException if an input/output error occurs
*/
private void trashResource(HttpServletRequest req, HttpServletResponse resp, String path) throws IOException {
- User user = getUser(req);
+ final User user = getUser(req);
User owner = getOwner(req);
Object resource = null;
try {
}
try {
- if (resource instanceof FolderDTO) {
- FolderDTO folder = (FolderDTO) resource;
- getService().moveFolderToTrash(user.getId(), folder.getId());
+ if (resource instanceof Folder) {
+ final Folder folderLocal = (Folder) resource;
+ new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ getService().moveFolderToTrash(user.getId(), folderLocal.getId());
+ return null;
+ }
+ });
} else {
- FileHeaderDTO file = (FileHeaderDTO) resource;
- getService().moveFileToTrash(user.getId(), file.getId());
+ final FileHeader fileLocal = (FileHeader) resource;
+ new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ getService().moveFileToTrash(user.getId(), fileLocal.getId());
+ return null;
+ }
+ });
}
} catch (InsufficientPermissionsException e) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
resp.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
} catch (RpcException e) {
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
+ } catch (Exception e) {
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
}
}
* @throws IOException if an input/output error occurs
*/
private void restoreResource(HttpServletRequest req, HttpServletResponse resp, String path) throws IOException {
- User user = getUser(req);
+ final User user = getUser(req);
User owner = getOwner(req);
Object resource = null;
try {
}
try {
- if (resource instanceof FolderDTO) {
- FolderDTO folder = (FolderDTO) resource;
- getService().removeFolderFromTrash(user.getId(), folder.getId());
+ if (resource instanceof Folder) {
+ final Folder folderLocal = (Folder) resource;
+ new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ getService().removeFolderFromTrash(user.getId(), folderLocal.getId());
+ return null;
+ }
+ });
} else {
- FileHeaderDTO file = (FileHeaderDTO) resource;
- getService().removeFileFromTrash(user.getId(), file.getId());
+ final FileHeader fileLocal = (FileHeader) resource;
+ new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ getService().removeFileFromTrash(user.getId(), fileLocal.getId());
+ return null;
+ }
+ });
}
} catch (InsufficientPermissionsException e) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
resp.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
} catch (RpcException e) {
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
+ } catch (Exception e) {
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
}
}
* @throws IOException if an input/output error occurs
*/
private void updateResource(HttpServletRequest req, HttpServletResponse resp, String path) throws IOException {
- User user = getUser(req);
+ final User user = getUser(req);
User owner = getOwner(req);
Object resource = null;
+
try {
resource = getService().getResourceAtPath(owner.getId(), path, false);
} catch (ObjectNotFoundException e) {
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
return;
}
- //use utf-8 encoding for reading request
- BufferedReader reader = new BufferedReader(new InputStreamReader(req.getInputStream(),"UTF-8"));
StringBuffer input = new StringBuffer();
- String line = null;
JSONObject json = null;
- while ((line = reader.readLine()) != null)
- input.append(line);
- reader.close();
+ if (req.getContentType() != null && req.getContentType().startsWith("application/x-www-form-urlencoded"))
+ input.append(req.getParameter(RESOURCE_UPDATE_PARAMETER));
+ else {
+ // Assume application/json
+ BufferedReader reader = new BufferedReader(new InputStreamReader(req.getInputStream(),"UTF-8"));
+ String line = null;
+ while ((line = reader.readLine()) != null)
+ input.append(line);
+ reader.close();
+ }
try {
json = new JSONObject(input.toString());
if (logger.isDebugEnabled())
logger.debug("JSON update: " + json);
- if (resource instanceof FolderDTO) {
- FolderDTO folder = (FolderDTO) resource;
+ if (resource instanceof Folder) {
+ final Folder folderLocal = (Folder) resource;
String name = json.optString("name");
- if (!name.isEmpty()){
- try {
- name = URLDecoder.decode(name, "UTF-8");
- } catch (IllegalArgumentException e) {
- resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
- return;
- }
- getService().modifyFolder(user.getId(), folder.getId(), name);
- FolderDTO folderUpdated = getService().getFolder(user.getId(), folder.getId());
- String parentUrl =URLDecoder.decode(getContextPath(req, true),"UTF-8");
- String fpath = URLDecoder.decode(req.getPathInfo(), "UTF-8");
- parentUrl = parentUrl.replaceAll(fpath, "");
- if(!parentUrl.endsWith("/"))
- parentUrl = parentUrl+"/";
- parentUrl = parentUrl+folderUpdated.getOwner().getUsername()+PATH_FILES+folderUpdated.getPath();
- resp.getWriter().println(parentUrl);
- }
-
+ if (!isValidResourceName(name)) {
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
JSONArray permissions = json.optJSONArray("permissions");
- if (permissions != null) {
- Set<PermissionDTO> perms = parsePermissions(user, permissions);
- getService().setFolderPermissions(user.getId(), folder.getId(), perms);
+ Set<Permission> perms = null;
+ if (permissions != null)
+ perms = parsePermissions(user, permissions);
+ Boolean readForAll = null;
+ if (json.opt("readForAll") != null)
+ readForAll = json.optBoolean("readForAll");
+ if (!name.isEmpty() || permissions != null || readForAll != null) {
+ final String fName = name.isEmpty()? null: name;
+ final Boolean freadForAll = readForAll;
+ final Set<Permission> fPerms = perms;
+ Folder folderUpdated = new TransactionHelper<Folder>().tryExecute(new Callable<Folder>() {
+ @Override
+ public Folder call() throws Exception {
+ return getService().updateFolder(user.getId(), folderLocal.getId(), fName, freadForAll, fPerms);
+ }
+
+ });
+ resp.getWriter().println(getNewUrl(req, folderUpdated));
}
} else {
- FileHeaderDTO file = (FileHeaderDTO) resource;
+ final FileHeader fileLocal = (FileHeader) resource;
String name = null;
if (json.opt("name") != null)
name = json.optString("name");
+ if (name != null)
+ if (!isValidResourceName(name)) {
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+ Long modificationDate = null;
+ if (json.optLong("modificationDate") != 0)
+ modificationDate = json.optLong("modificationDate");
+ Boolean versioned = null;
+ if (json.opt("versioned") != null)
+ versioned = json.getBoolean("versioned");
JSONArray tagset = json.optJSONArray("tags");
String tags = null;
StringBuffer t = new StringBuffer();
t.append(tagset.getString(i) + ',');
tags = t.toString();
}
- if (name != null || tags != null)
- getService().updateFile(user.getId(), file.getId(), name, tags);
-
JSONArray permissions = json.optJSONArray("permissions");
- Set<PermissionDTO> perms = null;
+ Set<Permission> perms = null;
if (permissions != null)
perms = parsePermissions(user, permissions);
Boolean readForAll = null;
if (json.opt("readForAll") != null)
readForAll = json.optBoolean("readForAll");
- if (perms != null || readForAll != null)
- getService().setFilePermissions(user.getId(), file.getId(), readForAll, perms);
-
- if (json.opt("versioned") != null) {
- boolean versioned = json.getBoolean("versioned");
- getService().toggleFileVersioning(user.getId(), file.getId(), versioned);
+ if (name != null || tags != null || modificationDate != null
+ || versioned != null || perms != null
+ || readForAll != null) {
+ final String fName = name;
+ final String fTags = tags;
+ final Date mDate = modificationDate != null? new Date(modificationDate): null;
+ final Boolean fVersioned = versioned;
+ final Boolean fReadForAll = readForAll;
+ final Set<Permission> fPerms = perms;
+ new TransactionHelper<Object>().tryExecute(new Callable<Object>() {
+ @Override
+ public Object call() throws Exception {
+ getService().updateFile(user.getId(), fileLocal.getId(),
+ fName, fTags, mDate, fVersioned,
+ fReadForAll, fPerms);
+ return null;
+ }
+
+ });
}
}
} catch (JSONException e) {
resp.sendError(HttpServletResponse.SC_CONFLICT, e.getMessage());
} catch (RpcException e) {
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
+ } catch (Exception e) {
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
+ return;
}
}
/**
+ * Returns the new URL of an updated folder.
+ */
+ private String getNewUrl(HttpServletRequest req, Folder folder) throws UnsupportedEncodingException {
+ String parentUrl = URLDecoder.decode(getContextPath(req, true),"UTF-8");
+ String fpath = URLDecoder.decode(getRelativePath(req), "UTF-8");
+ if (parentUrl.indexOf(fpath) != -1)
+ parentUrl = parentUrl.substring(0, parentUrl.indexOf(fpath));
+ if(!parentUrl.endsWith("/"))
+ parentUrl = parentUrl+"/";
+ parentUrl = parentUrl+folder.getOwner().getUsername()+PATH_FILES+folder.getPath();
+ return parentUrl;
+ }
+
+ /**
* Helper method to convert a JSON array of permissions into a set of
- * PermissionDTO objects.
+ * Permission objects.
*
* @param user the current user
* @param permissions the JSON array to parse
* @throws JSONException if there was an error parsing the JSON object
* @throws RpcException if there was an error communicating with the EJB
* @throws ObjectNotFoundException if the user could not be found
+ * @throws UnsupportedEncodingException
*/
- private Set<PermissionDTO> parsePermissions(User user, JSONArray permissions)
- throws JSONException, RpcException, ObjectNotFoundException {
+ private Set<Permission> parsePermissions(User user, JSONArray permissions)
+ throws JSONException, RpcException, ObjectNotFoundException, UnsupportedEncodingException {
if (permissions == null)
return null;
- Set<PermissionDTO> perms = new HashSet<PermissionDTO>();
+ Set<Permission> perms = new HashSet<Permission>();
for (int i = 0; i < permissions.length(); i++) {
JSONObject j = permissions.getJSONObject(i);
- PermissionDTO perm = new PermissionDTO();
+ Permission perm = new Permission();
perm.setModifyACL(j.optBoolean("modifyACL"));
perm.setRead(j.optBoolean("read"));
perm.setWrite(j.optBoolean("write"));
User u = getService().findUser(permUser);
if (u == null)
throw new ObjectNotFoundException("User " + permUser + " not found");
- perm.setUser(u.getDTO());
+ perm.setUser(u);
}
+ // 31/8/2009: Add optional groupUri which takes priority if it exists
+ String permGroupUri = j.optString("groupUri");
String permGroup = j.optString("group");
- if (!permGroup.isEmpty()) {
- GroupDTO g = getService().getGroup(user.getId(), permGroup);
+ if (!permGroupUri.isEmpty()) {
+ String[] names = permGroupUri.split("/");
+ String grp = URLDecoder.decode(names[names.length - 1], "UTF-8");
+ String usr = URLDecoder.decode(names[names.length - 3], "UTF-8");
+ User u = getService().findUser(usr);
+ if (u == null)
+ throw new ObjectNotFoundException("User " + permUser + " not found");
+ Group g = getService().getGroup(u.getId(), grp);
perm.setGroup(g);
}
- if (permUser.isEmpty() && permGroup.isEmpty() ||
- permUser.isEmpty() && permGroup.isEmpty())
+ else if (!permGroup.isEmpty()) {
+ Group g = getService().getGroup(user.getId(), permGroup);
+ perm.setGroup(g);
+ }
+ if (permUser.isEmpty() && permGroupUri.isEmpty() && permGroup.isEmpty())
throw new JSONException("A permission must correspond to either a user or a group");
perms.add(perm);
}
* @param folderName the name of the new folder
* @throws IOException if an input/output error occurs
*/
- private void createFolder(HttpServletRequest req, HttpServletResponse resp, String path, String folderName) throws IOException {
+ private void createFolder(HttpServletRequest req, HttpServletResponse resp, String path, final String folderName) throws IOException {
if (logger.isDebugEnabled())
logger.debug("Creating folder " + folderName + " in '" + path);
- User user = getUser(req);
+ final User user = getUser(req);
User owner = getOwner(req);
boolean exists = true;
try {
return;
}
try {
- if (parent instanceof FolderDTO) {
- FolderDTO folder = (FolderDTO) parent;
- getService().createFolder(user.getId(), folder.getId(), folderName);
- String newResource = getContextPath(req, true) + folderName;
+ if (parent instanceof Folder) {
+ final Folder folderLocal = (Folder) parent;
+ Folder newFolder = new TransactionHelper<Folder>().tryExecute(new Callable<Folder>() {
+ @Override
+ public Folder call() throws Exception {
+ return getService().createFolder(user.getId(), folderLocal.getId(), folderName);
+ }
+
+ });
+ String newResource = getApiRoot() + newFolder.getURI();
resp.setHeader("Location", newResource);
resp.setContentType("text/plain");
PrintWriter out = resp.getWriter();
} catch (RpcException e) {
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path + folderName);
return;
+ } catch (Exception e) {
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
+ return;
}
resp.setStatus(HttpServletResponse.SC_CREATED);
}
if (logger.isDebugEnabled())
logger.debug("Updating resource: " + path);
- User user = getUser(req);
+ final User user = getUser(req);
User owner = getOwner(req);
boolean exists = true;
Object resource = null;
- FileHeaderDTO file = null;
+ FileHeader fileLocal = null;
try {
resource = getService().getResourceAtPath(owner.getId(), path, false);
} catch (ObjectNotFoundException e) {
}
if (exists)
- if (resource instanceof FileHeaderDTO)
- file = (FileHeaderDTO) resource;
+ if (resource instanceof FileHeader)
+ fileLocal = (FileHeader) resource;
else {
resp.sendError(HttpServletResponse.SC_CONFLICT, path + " is a folder");
return;
resourceInputStream = req.getInputStream();
try {
- FolderDTO folder = null;
+ Folder folderLocal = null;
Object parent = getService().getResourceAtPath(owner.getId(), getParentPath(path), true);
- if (!(parent instanceof FolderDTO)) {
+ if (!(parent instanceof Folder)) {
resp.sendError(HttpServletResponse.SC_CONFLICT);
return;
}
- folder = (FolderDTO) parent;
- String name = getLastElement(path);
- String mimeType = context.getMimeType(name);
+ folderLocal = (Folder) parent;
+ final String name = getLastElement(path);
+ final String mimeType = context.getMimeType(name);
File uploadedFile = null;
try {
uploadedFile = getService().uploadFile(resourceInputStream, user.getId());
} catch (IOException ex) {
throw new GSSIOException(ex, false);
}
- FileHeaderDTO fileDTO = null;
+ FileHeader fileTemp = null;
+ final File uploadedf = uploadedFile;
+ final Folder parentf = folderLocal;
+ final FileHeader f = fileLocal;
if (exists)
- fileDTO = getService().updateFileContents(user.getId(), file.getId(), mimeType, uploadedFile);
+ fileTemp = new TransactionHelper<FileHeader>().tryExecute(new Callable<FileHeader>() {
+ @Override
+ public FileHeader call() throws Exception {
+ return getService().updateFileContents(user.getId(), f.getId(), mimeType, uploadedf.getCanonicalFile().length(), uploadedf.getAbsolutePath());
+ }
+ });
else
- fileDTO = getService().createFile(user.getId(), folder.getId(), name, mimeType, uploadedFile);
- getService().updateAccounting(user, new Date(), fileDTO.getFileSize());
- getService().removeFileUploadProgress(user.getId(), fileDTO.getName());
+ fileTemp = new TransactionHelper<FileHeader>().tryExecute(new Callable<FileHeader>() {
+ @Override
+ public FileHeader call() throws Exception {
+ return getService().createFile(user.getId(), parentf.getId(), name, mimeType, uploadedf.getCanonicalFile().length(), uploadedf.getAbsolutePath());
+ }
+
+ });
+ updateAccounting(owner, new Date(), fileTemp.getCurrentBody().getFileSize());
+ getService().removeFileUploadProgress(user.getId(), fileTemp.getName());
} catch(ObjectNotFoundException e) {
result = false;
} catch (RpcException e) {
} catch (QuotaExceededException e) {
resp.sendError(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE, e.getMessage());
return;
+ } catch (Exception e) {
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
+ return;
}
if (result) {
if (logger.isDebugEnabled())
logger.debug("Deleting resource '" + path);
path = URLDecoder.decode(path, "UTF-8");
- User user = getUser(req);
+ final User user = getUser(req);
User owner = getOwner(req);
boolean exists = true;
Object object = null;
return;
}
- FolderDTO folder = null;
- FileHeaderDTO file = null;
- if (object instanceof FolderDTO)
- folder = (FolderDTO) object;
+ Folder folderLocal = null;
+ FileHeader fileLocal = null;
+ if (object instanceof Folder)
+ folderLocal = (Folder) object;
else
- file = (FileHeaderDTO) object;
+ fileLocal = (FileHeader) object;
- if (file != null)
+ if (fileLocal != null)
try {
- getService().deleteFile(user.getId(), file.getId());
+ final FileHeader f = fileLocal;
+ new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ getService().deleteFile(user.getId(), f.getId());
+ return null;
+ }
+ });
} catch (InsufficientPermissionsException e) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
return;
} catch (RpcException e) {
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
+ } catch (Exception e) {
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ return;
}
- else if (folder != null)
+ else if (folderLocal != null)
try {
- getService().deleteFolder(user.getId(), folder.getId());
+ final Folder fo = folderLocal;
+ new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ getService().deleteFolder(user.getId(), fo.getId());
+ return null;
+ }
+ });
} catch (InsufficientPermissionsException e) {
resp.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
return;
} catch (RpcException e) {
resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
+ } catch (Exception e) {
+ resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ return;
}
resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
return;
* @throws InsufficientPermissionsException if the user does not have
* the necessary privileges to read the directory
*/
- private InputStream renderJson(User user, FolderDTO folder) throws IOException,
+ private InputStream renderJson(User user, Folder folder) throws IOException,
ServletException, InsufficientPermissionsException {
+ try {
+ folder = getService().expandFolder(folder);
+ } catch (ObjectNotFoundException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ } catch (RpcException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
JSONObject json = new JSONObject();
try {
json.put("name", folder.getName()).
put("owner", folder.getOwner().getUsername()).
put("createdBy", folder.getAuditInfo().getCreatedBy().getUsername()).
put("creationDate", folder.getAuditInfo().getCreationDate().getTime()).
- put("deleted", folder.isDeleted());
+ put("deleted", folder.isDeleted()).
+ put("shared", folder.getShared()).
+ put("readForAll", folder.isReadForAll());
+
if (folder.getAuditInfo().getModifiedBy() != null)
json.put("modifiedBy", folder.getAuditInfo().getModifiedBy().getUsername()).
put("modificationDate", folder.getAuditInfo().getModificationDate().getTime());
json.put("parent", j);
}
List<JSONObject> subfolders = new ArrayList<JSONObject>();
- for (FolderDTO f: folder.getSubfolders())
+ for (Folder f: folder.getSubfolders())
if (!f.isDeleted()) {
JSONObject j = new JSONObject();
j.put("name", f.getName()).
}
json.put("folders", subfolders);
List<JSONObject> files = new ArrayList<JSONObject>();
- List<FileHeaderDTO> fileHeaders = getService().getFiles(user.getId(), folder.getId(), false);
- for (FileHeaderDTO f: fileHeaders) {
+ List<FileHeader> fileHeaders = getService().getFiles(user.getId(), folder.getId(), false);
+ for (FileHeader f: fileHeaders) {
JSONObject j = new JSONObject();
j.put("name", f.getName()).
put("owner", f.getOwner().getUsername()).
put("deleted", f.isDeleted()).
- put("version", f.getVersion()).
- put("content", f.getMimeType()).
- put("size", f.getFileSize()).
+ put("version", f.getCurrentBody().getVersion()).
+ put("content", f.getCurrentBody().getMimeType()).
+ put("size", f.getCurrentBody().getFileSize()).
+ put("shared", f.getShared()).
+ put("versioned",f.isVersioned()).
put("creationDate", f.getAuditInfo().getCreationDate().getTime()).
put("path", f.getFolder().getPath()).
put("uri", getApiRoot() + f.getURI());
files.add(j);
}
json.put("files", files);
- Set<PermissionDTO> perms = getService().getFolderPermissions(user.getId(), folder.getId());
+ Set<Permission> perms = getService().getFolderPermissions(user.getId(), folder.getId());
json.put("permissions", renderJson(perms));
} catch (JSONException e) {
throw new ServletException(e);
* @throws InsufficientPermissionsException
* @throws ObjectNotFoundException
*/
- private String renderJsonMetadata(User user, FolderDTO folder)
+ private String renderJsonMetadata(User user, Folder folder)
throws ServletException, InsufficientPermissionsException {
// Check if the user has read permission.
try {
JSONObject json = new JSONObject();
try {
- json.put("name", folder.getName()).
+ json.put("name", URLEncoder.encode(folder.getName(), "UTF-8")).
put("owner", folder.getOwner().getUsername()).
put("createdBy", folder.getAuditInfo().getCreatedBy().getUsername()).
put("creationDate", folder.getAuditInfo().getCreationDate().getTime()).
} catch (JSONException e) {
throw new ServletException(e);
}
- return json.toString();
+ catch (UnsupportedEncodingException e) {
+ throw new ServletException(e);
+ }
+ return json.toString();
}
/**
* @throws InsufficientPermissionsException if the user does not have
* the necessary privileges to read the directory
*/
- private String renderJson(User user, FileHeaderDTO file, FileBodyDTO oldBody)
+ private String renderJson(User user, FileHeader file, FileBody oldBody)
throws ServletException, InsufficientPermissionsException {
JSONObject json = new JSONObject();
try {
+ file=getService().expandFile(file);
// Need to encode file name in order to properly display it in the web client.
json.put("name", URLEncoder.encode(file.getName(),"UTF-8")).
put("owner", file.getOwner().getUsername()).
put("versioned", file.isVersioned()).
- put("version", oldBody != null ? oldBody.getVersion() : file.getVersion()).
+ put("version", oldBody != null ? oldBody.getVersion() : file.getCurrentBody().getVersion()).
put("readForAll", file.isReadForAll()).
- put("tags", renderJson(file.getTags())).
+ put("shared", file.getShared()).
+ put("tags", renderJson(file.getFileTagsAsStrings())).
put("path", file.getFolder().getPath()).
put("uri", getApiRoot() + file.getURI()).
put("deleted", file.isDeleted());
put("creationDate", file.getAuditInfo().getCreationDate().getTime()).
put("modifiedBy", file.getAuditInfo().getModifiedBy().getUsername()).
put("modificationDate", file.getAuditInfo().getModificationDate().getTime()).
- put("content", file.getMimeType()).
- put("size", file.getFileSize());
- Set<PermissionDTO> perms = getService().getFilePermissions(user.getId(), file.getId());
+ put("content", file.getCurrentBody().getMimeType()).
+ put("size", file.getCurrentBody().getFileSize());
+ Set<Permission> perms = getService().getFilePermissions(user.getId(), file.getId());
json.put("permissions", renderJson(perms));
} catch (JSONException e) {
throw new ServletException(e);
* @throws JSONException
* @throws UnsupportedEncodingException
*/
- private JSONArray renderJson(Set<PermissionDTO> permissions) throws JSONException, UnsupportedEncodingException {
+ private JSONArray renderJson(Set<Permission> permissions) throws JSONException, UnsupportedEncodingException {
JSONArray perms = new JSONArray();
- for (PermissionDTO p: permissions) {
+ for (Permission p: permissions) {
JSONObject permission = new JSONObject();
permission.put("read", p.hasRead()).put("write", p.hasWrite()).put("modifyACL", p.hasModifyACL());
if (p.getUser() != null)
permission.put("user", p.getUser().getUsername());
- if (p.getGroup() != null)
+ if (p.getGroup() != null) {
+ Group group = p.getGroup();
+ permission.put("groupUri", getApiRoot() + group.getOwner().getUsername() + PATH_GROUPS + "/" + URLEncoder.encode(group.getName(),"UTF-8"));
permission.put("group", URLEncoder.encode(p.getGroup().getName(),"UTF-8"));
+ }
perms.put(permission);
}
return perms;
private long fileSize = -100;
- private long tenKBRead = -1;
-
private Long userId;
private String filename;
filename = aFilename;
}
+ @Override
public void update(long bytesRead, long contentLength, int items) {
//monitoring per percent of bytes uploaded
bytesTransferred = bytesRead;
if (fileSize != contentLength)
fileSize = contentLength;
int percent = new Long(bytesTransferred * 100 / fileSize).intValue();
-
if (percent < 5 || percent % TRACK_PROGRESS_PERCENT == 0 )
if (percent != percentLogged){
percentLogged = percent;
}
}
}
+
+ /**
+ * Return an InputStream to an HTML representation of the contents of this
+ * directory.
+ *
+ * @param contextPath Context path to which our internal paths are relative
+ * @param path the requested path to the resource
+ * @param folder the specified directory
+ * @param user the specified user
+ * @return an input stream with the rendered contents
+ * @throws IOException
+ * @throws ServletException
+ */
+ private InputStream renderHtml(String contextPath, String path, Folder folder, User user)
+ throws IOException, ServletException {
+ String name = folder.getName();
+ // Prepare a writer to a buffered area
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ OutputStreamWriter osWriter = new OutputStreamWriter(stream, "UTF8");
+ PrintWriter writer = new PrintWriter(osWriter);
+ StringBuffer sb = new StringBuffer();
+ // rewriteUrl(contextPath) is expensive. cache result for later reuse
+ String rewrittenContextPath = rewriteUrl(contextPath);
+ // Render the page header
+ sb.append("<html>\r\n");
+ sb.append("<head>\r\n");
+ sb.append("<title>");
+ sb.append("Index of " + name);
+ sb.append("</title>\r\n");
+ sb.append("<STYLE><!--");
+ sb.append(GSS_CSS);
+ sb.append("--></STYLE> ");
+ sb.append("</head>\r\n");
+ sb.append("<body>");
+ sb.append("<h1>");
+ sb.append("Index of " + name);
+
+ // Render the link to our parent (if required)
+ String parentDirectory = path;
+ if (parentDirectory.endsWith("/"))
+ parentDirectory = parentDirectory.substring(0, parentDirectory.length() - 1);
+ int slash = parentDirectory.lastIndexOf('/');
+ if (slash >= 0) {
+ String parent = path.substring(0, slash);
+ sb.append(" - <a href=\"");
+ sb.append(rewrittenContextPath);
+ if (parent.equals(""))
+ parent = "/";
+ sb.append(parent);
+ if (!parent.endsWith("/"))
+ sb.append("/");
+ sb.append("\">");
+ sb.append("<b>");
+ sb.append("Up To " + parent);
+ sb.append("</b>");
+ sb.append("</a>");
+ }
+
+ sb.append("</h1>");
+ sb.append("<HR size=\"1\" noshade=\"noshade\">");
+
+ sb.append("<table width=\"100%\" cellspacing=\"0\"" + " cellpadding=\"5\" align=\"center\">\r\n");
+
+ // Render the column headings
+ sb.append("<tr>\r\n");
+ sb.append("<td align=\"left\"><font size=\"+1\"><strong>");
+ sb.append("Name");
+ sb.append("</strong></font></td>\r\n");
+ sb.append("<td align=\"center\"><font size=\"+1\"><strong>");
+ sb.append("Size");
+ sb.append("</strong></font></td>\r\n");
+ sb.append("<td align=\"right\"><font size=\"+1\"><strong>");
+ sb.append("Last modified");
+ sb.append("</strong></font></td>\r\n");
+ sb.append("</tr>");
+ // Render the directory entries within this directory
+ boolean shade = false;
+ Iterator iter = folder.getSubfolders().iterator();
+ while (iter.hasNext()) {
+ Folder subf = (Folder) iter.next();
+ if(subf.isReadForAll() && !subf.isDeleted()){
+ String resourceName = subf.getName();
+ if (resourceName.equalsIgnoreCase("WEB-INF") || resourceName.equalsIgnoreCase("META-INF"))
+ continue;
+
+ sb.append("<tr");
+ if (shade)
+ sb.append(" bgcolor=\"#eeeeee\"");
+ sb.append(">\r\n");
+ shade = !shade;
+
+ sb.append("<td align=\"left\"> \r\n");
+ sb.append("<a href=\"");
+ sb.append(rewrittenContextPath+path);
+ sb.append(rewriteUrl(resourceName));
+ sb.append("/");
+ sb.append("\"><tt>");
+ sb.append(RequestUtil.filter(resourceName));
+ sb.append("/");
+ sb.append("</tt></a></td>\r\n");
+
+ sb.append("<td align=\"right\"><tt>");
+ sb.append(" ");
+ sb.append("</tt></td>\r\n");
+
+ sb.append("<td align=\"right\"><tt>");
+ sb.append(getLastModifiedHttp(folder.getAuditInfo()));
+ sb.append("</tt></td>\r\n");
+
+ sb.append("</tr>\r\n");
+
+ }
+ }
+ List<FileHeader> files;
+ try {
+ files = getService().getFiles(user.getId(), folder.getId(), true);
+ } catch (ObjectNotFoundException e) {
+ throw new ServletException(e.getMessage());
+ } catch (InsufficientPermissionsException e) {
+ throw new ServletException(e.getMessage());
+ } catch (RpcException e) {
+ throw new ServletException(e.getMessage());
+ }
+ for (FileHeader file : files)
+ //Display only file resources that are marked as public and are not deleted
+ if(file.isReadForAll() && !file.isDeleted()){
+ String resourceName = file.getName();
+ if (resourceName.equalsIgnoreCase("WEB-INF") || resourceName.equalsIgnoreCase("META-INF"))
+ continue;
+
+ sb.append("<tr");
+ if (shade)
+ sb.append(" bgcolor=\"#eeeeee\"");
+ sb.append(">\r\n");
+ shade = !shade;
+
+ sb.append("<td align=\"left\"> \r\n");
+ sb.append("<a href=\"");
+ sb.append(rewrittenContextPath + path);
+ sb.append(rewriteUrl(resourceName));
+ sb.append("\"><tt>");
+ sb.append(RequestUtil.filter(resourceName));
+ sb.append("</tt></a></td>\r\n");
+
+ sb.append("<td align=\"right\"><tt>");
+ sb.append(renderSize(file.getCurrentBody().getFileSize()));
+ sb.append("</tt></td>\r\n");
+
+ sb.append("<td align=\"right\"><tt>");
+ sb.append(getLastModifiedHttp(file.getAuditInfo()));
+ sb.append("</tt></td>\r\n");
+
+ sb.append("</tr>\r\n");
+ }
+
+ // Render the page footer
+ sb.append("</table>\r\n");
+
+ sb.append("<HR size=\"1\" noshade=\"noshade\">");
+ sb.append("</body>\r\n");
+ sb.append("</html>\r\n");
+
+ // Return an input stream to the underlying bytes
+ writer.write(sb.toString());
+ writer.flush();
+ return new ByteArrayInputStream(stream.toByteArray());
+
+ }
}