better matching of MS Office mime types (in showing file icons and indexing)
[pithos] / src / gr / ebs / gss / server / ejb / ExternalAPIBean.java
index 28af26a..b6b90b8 100644 (file)
@@ -56,6 +56,7 @@ import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Locale;
 import java.util.Random;
 import java.util.Set;
 import java.util.StringTokenizer;
@@ -263,7 +264,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
        }
 
        @Override
-       public void createFolder(Long userId, Long parentId, String name)
+       public FolderDTO createFolder(Long userId, Long parentId, String name)
                        throws DuplicateNameException, ObjectNotFoundException, InsufficientPermissionsException {
                // Validate.
                if (userId == null)
@@ -290,7 +291,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
                                        " to write to this folder");
 
                // Do the actual work.
-               createFolder(name, parent, creator);
+               return createFolder(name, parent, creator);
        }
 
        /**
@@ -299,8 +300,9 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
         * @param name
         * @param parent
         * @param creator
+        * @return the new folder
         */
-       private void createFolder(String name, Folder parent, User creator) {
+       private FolderDTO createFolder(String name, Folder parent, User creator) {
                Folder folder = new Folder();
                folder.setName(name);
                if (parent != null) {
@@ -336,10 +338,12 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
                        folder.addPermission(permission);
                }
                dao.create(folder);
+               return folder.getDTO();
        }
 
        /*
-        * (non-Javadoc)
+        * Deletes the given folder and all its subfolders and files
+        * Only the permissions for top folder are checked
         *
         * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteFolder(java.lang.Long,
         *      java.lang.Long)
@@ -361,10 +365,29 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
                        logger.info("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
                        throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
                }
+               removeSubfolderFiles(folder);
                parent.removeSubfolder(folder);
                dao.delete(folder);
        }
 
+       /**
+        * Traverses the folder and deletes all actual files (file system)
+        * regardless of permissions
+        *
+        * @param folder
+        */
+       private void removeSubfolderFiles(Folder folder) {
+               //remove files for all subfolders
+               for (Folder subfolder:folder.getSubfolders())
+                       removeSubfolderFiles(subfolder);
+               //remove this folder's file bodies (actual files)
+               for (FileHeader file:folder.getFiles()) {
+                       for (FileBody body:file.getBodies())
+                               deleteActualFile(body.getStoredFilePath());
+                       indexFile(file.getId(), true);
+               }
+       }
+
        @SuppressWarnings("unchecked")
        public List<FolderDTO> getSubfolders(Long userId, Long folderId)
                        throws ObjectNotFoundException, InsufficientPermissionsException {
@@ -385,7 +408,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
        }
 
        @Override
-       public void modifyFolder(Long userId, Long folderId, String folderName)
+       public FolderDTO modifyFolder(Long userId, Long folderId, String folderName)
                        throws InsufficientPermissionsException, ObjectNotFoundException, DuplicateNameException {
 
                // Validate.
@@ -409,6 +432,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
                // Do the actual modification.
                folder.setName(folderName);
                dao.update(folder);
+               return folder.getDTO();
        }
 
        /*
@@ -478,7 +502,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
                        // Supply a more accurate problem description.
                        throw new GSSIOException("Problem creating file",ioe);
                }
-               return createFile(userId, folderId, name, mimeType, file);
+               return createFile(userId, folderId, name, mimeType, file.length(), file.getAbsolutePath());
        }
 
        /* (non-Javadoc)
@@ -570,15 +594,20 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
                final User user = dao.getEntityById(User.class, userId);
                if (!file.hasDeletePermission(user))
                        throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
-               for (final FileBody body : file.getBodies()) {
-                       final File fileContents = new File(body.getStoredFilePath());
-                       if (!fileContents.delete())
-                               logger.error("Could not delete file " + body.getStoredFilePath());
-               }
+               for (final FileBody body : file.getBodies())
+                       deleteActualFile(body.getStoredFilePath());
                dao.delete(file);
                indexFile(fileId, true);
        }
 
+       private void deleteActualFile(String filePath) {
+               if (filePath == null)
+                       return;
+               File file = new File(filePath);
+               if (!file.delete())
+                       logger.error("Could not delete file " + filePath);
+       }
+
        /*
         * (non-Javadoc)
         *
@@ -818,7 +847,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
                        // Supply a more accurate problem description.
                        throw new GSSIOException("Problem creating file",ioe);
                }
-               return updateFileContents(userId, fileId, mimeType, file);
+               return updateFileContents(userId, fileId, mimeType, file.length(), file.getAbsolutePath());
        }
 
        @Override
@@ -871,6 +900,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
                User user = dao.getEntityById(User.class, userId);
                if (!file.hasReadPermission(user) || !destination.hasWritePermission(user))
                        throw new InsufficientPermissionsException("You don't have the necessary permissions");
+               boolean versioned = file.isVersioned();
                int versionsNumber = file.getBodies().size();
                FileBody oldestBody = file.getBodies().get(0);
                assert oldestBody != null;
@@ -878,6 +908,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
                try {
                        createFile(user.getId(), destination.getId(), destName, oldestBody.getMimeType(), new FileInputStream(contents));
                        FileHeader copiedFile = dao.getFile(destination.getId(), destName);
+                       copiedFile.setVersioned(versioned);
                        dao.flush();
                        if (versionsNumber > 1)
                                for (int i = 1; i < versionsNumber; i++) {
@@ -1053,7 +1084,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
        }
 
        @Override
-       public void moveFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, InsufficientPermissionsException, DuplicateNameException, GSSIOException, QuotaExceededException {
+       public void moveFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, InsufficientPermissionsException, QuotaExceededException {
                if (userId == null)
                        throw new ObjectNotFoundException("No user specified");
                if (ownerId == null)
@@ -1071,7 +1102,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
        }
 
        @Override
-       public void moveFile(Long userId, Long fileId, Long destId, String destName) throws InsufficientPermissionsException, ObjectNotFoundException, DuplicateNameException, GSSIOException, QuotaExceededException {
+       public void moveFile(Long userId, Long fileId, Long destId, String destName) throws InsufficientPermissionsException, ObjectNotFoundException, QuotaExceededException {
                if (userId == null)
                        throw new ObjectNotFoundException("No user specified");
                if (fileId == null)
@@ -1087,16 +1118,34 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
                User owner = dao.getEntityById(User.class, userId);
                if (!file.hasDeletePermission(owner) || !destination.hasWritePermission(owner))
                        throw new InsufficientPermissionsException("User " + owner.getId() + " cannot move file " + file.getName() + "(" + file.getId() + ")");
-               FileBody body = file.getCurrentBody();
-               assert body != null;
-               File contents = new File(body.getStoredFilePath());
-               try {
-                       createFile(owner.getId(), destination.getId(), destName, body.getMimeType(), new FileInputStream(contents));
-               } catch (FileNotFoundException e) {
-                       throw new ObjectNotFoundException("File contents not found for file " + body.getStoredFilePath());
-               }
-               deleteFile(userId, fileId);
 
+               // if the destination folder belongs to another user:
+               if (!file.getOwner().equals(destination.getOwner())) {
+                       // (a) check if the destination quota allows the move
+                       if(getQuotaLeft(destination.getOwner().getId()) < file.getTotalSize())
+                               throw new QuotaExceededException("Not enough free space available");
+                       User newOwner = destination.getOwner();
+                       // (b) if quota OK, change the owner of the file
+                       file.setOwner(newOwner);
+                       // if the file has no permission for the new owner, add it
+                       Permission ownerPermission = null;
+                       for (final Permission p : file.getPermissions())
+                               if (p.getUser() != null)
+                                       if (p.getUser().equals(newOwner)) {
+                                               ownerPermission = p;
+                                               break;
+                                       }
+                       if (ownerPermission == null) {
+                               ownerPermission = new Permission();
+                               ownerPermission.setUser(newOwner);
+                               file.addPermission(ownerPermission);
+                       }
+                       ownerPermission.setRead(true);
+                       ownerPermission.setWrite(true);
+                       ownerPermission.setModifyACL(true);
+               }
+               // move the file to the destination folder
+               file.setFolder(destination);
        }
 
        @Override
@@ -1752,7 +1801,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
         * @see gr.ebs.gss.server.ejb.ExternalAPI#moveFiles(java.lang.Long, java.util.List, java.lang.Long)
         */
        @Override
-       public void moveFiles(Long userId, List<Long> fileIds, Long destId) throws InsufficientPermissionsException, ObjectNotFoundException, DuplicateNameException, GSSIOException, QuotaExceededException {
+       public void moveFiles(Long userId, List<Long> fileIds, Long destId) throws InsufficientPermissionsException, ObjectNotFoundException, QuotaExceededException {
                for(Long l : fileIds){
                        FileHeader file = dao.getEntityById(FileHeader.class, l);
                        moveFile(userId, l, destId, file.getName());
@@ -1768,7 +1817,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
                if (userId == null)
                        throw new ObjectNotFoundException("No user specified");
                final User user = dao.getEntityById(User.class, userId);
-               List<File> filesToRemove = new ArrayList<File>();
+               List<String> filesToRemove = new ArrayList<String>();
                //first delete database objects
                for(Long fileId : fileIds){
                        if (fileId == null)
@@ -1781,16 +1830,13 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
                                throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
 
                        parent.removeFile(file);
-                       for (final FileBody body : file.getBodies()) {
-                               final File fileContents = new File(body.getStoredFilePath());
-                               filesToRemove.add(fileContents);
-                       }
+                       for (final FileBody body : file.getBodies())
+                               filesToRemove.add(body.getStoredFilePath());
                        dao.delete(file);
                }
                //then remove physical files if everything is ok
-               for(File physicalFile : filesToRemove)
-                       if (!physicalFile.delete())
-                               logger.error("Could not delete file " + physicalFile.getPath());
+               for(String physicalFileName : filesToRemove)
+                       deleteActualFile(physicalFileName);
                //then unindex deleted files
                for(Long fileId : fileIds)
                        indexFile(fileId, true);
@@ -1910,9 +1956,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
                                if(b.getVersion() == body.getVersion()-1)
                                        header.setCurrentBody(b);
                }
-               final File fileContents = new File(body.getStoredFilePath());
-               if (!fileContents.delete())
-                       logger.error("Could not delete file " + body.getStoredFilePath());
+               deleteActualFile(body.getStoredFilePath());
                header.getBodies().remove(body);
 
 
@@ -1956,9 +2000,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
                while(it.hasNext()){
                        FileBody body = it.next();
                        if(!body.equals(header.getCurrentBody())){
-                               final File fileContents = new File(body.getStoredFilePath());
-                               if (!fileContents.delete())
-                                       logger.error("Could not delete file " + body.getStoredFilePath());
+                               deleteActualFile(body.getStoredFilePath());
                                it.remove();
                                dao.delete(body);
                        }
@@ -2139,7 +2181,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
                }
        }
 
-       public FileHeaderDTO createFile(Long userId, Long folderId, String name, String mimeType, File fileObject)
+       public FileHeaderDTO createFile(Long userId, Long folderId, String name, String mimeType, long fileSize, String filePath)
                        throws DuplicateNameException, ObjectNotFoundException, GSSIOException,
                        InsufficientPermissionsException, QuotaExceededException {
                // Validate.
@@ -2195,7 +2237,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
 
                // Create the file body.
                try {
-                       createFileBody(name, contentType, fileObject, file, auditInfo, owner);
+                       createFileBody(name, contentType, fileSize, filePath, file, auditInfo);
                } catch (FileNotFoundException e) {
                        throw new GSSIOException(e);
                }
@@ -2208,7 +2250,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
        /* (non-Javadoc)
         * @see gr.ebs.gss.server.ejb.ExternalAPI#updateFileContents(java.lang.Long, java.lang.Long, java.lang.String, java.io.InputStream)
         */
-       public FileHeaderDTO updateFileContents(Long userId, Long fileId, String mimeType, File fileObject) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
+       public FileHeaderDTO updateFileContents(Long userId, Long fileId, String mimeType, long fileSize, String filePath) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
                if (userId == null)
                        throw new ObjectNotFoundException("No user specified");
                if (fileId == null)
@@ -2233,7 +2275,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
                auditInfo.setModifiedBy(owner);
                auditInfo.setModificationDate(now);
                try {
-                       createFileBody(file.getName(), contentType, fileObject, file, auditInfo, owner);
+                       createFileBody(file.getName(), contentType, fileSize, filePath, file, auditInfo);
                } catch (FileNotFoundException e) {
                        throw new GSSIOException(e);
                }
@@ -2250,7 +2292,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
         */
        private String identifyMimeType(String filename) {
                if (filename.indexOf('.') != -1) {
-                       String extension = filename.substring(filename.lastIndexOf('.'));
+                       String extension = filename.substring(filename.lastIndexOf('.')).toLowerCase(Locale.ENGLISH);
                        if (".doc".equals(extension))
                                return "application/msword";
                        else if (".xls".equals(extension))
@@ -2259,6 +2301,16 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
                                return "application/vnd.ms-powerpoint";
                        else if (".pdf".equals(extension))
                                return "application/pdf";
+                       else if (".gif".equals(extension))
+                               return "image/gif";
+                       else if (".jpg".equals(extension) || ".jpeg".equals(extension) || ".jpe".equals(extension))
+                               return "image/jpeg";
+                       else if (".tiff".equals(extension) || ".tif".equals(extension))
+                               return "image/tiff";
+                       else if (".png".equals(extension))
+                               return "image/png";
+                       else if (".bmp".equals(extension))
+                               return "image/bmp";
                }
                // when all else fails assign the default mime type
                return DEFAULT_MIME_TYPE;
@@ -2270,23 +2322,25 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
         *
         * @param name the original file name
         * @param mimeType the content type
-        * @param uploadedFile the uploaded file contents
+        * @param fileSize the uploaded file size
+        * @param filePath the uploaded file full path
         * @param header the file header that will be associated with the new body
         * @param auditInfo the audit info
         * @param owner the owner of the file
         * @throws FileNotFoundException
         * @throws QuotaExceededException
         */
-       private void createFileBody(String name, String mimeType, File uploadedFile,
-                               FileHeader header, AuditInfo auditInfo, User owner)
+       private void createFileBody(String name, String mimeType, long fileSize, String filePath,
+                               FileHeader header, AuditInfo auditInfo)
                        throws FileNotFoundException, QuotaExceededException {
 
                long currentTotalSize = 0;
                if (!header.isVersioned() && header.getCurrentBody() != null && header.getBodies() != null)
                        currentTotalSize = header.getTotalSize();
                Long quotaLeft = getQuotaLeft(header.getOwner().getId());
-               if(quotaLeft < uploadedFile.length()-currentTotalSize) {
-                       uploadedFile.delete();
+               if(quotaLeft < fileSize-currentTotalSize) {
+                       // quota exceeded -> delete the file
+                       deleteActualFile(filePath);
                        throw new QuotaExceededException("Not enough free space available");
                }
 
@@ -2300,9 +2354,9 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
                else
                        body.setMimeType(mimeType);
                body.setAuditInfo(auditInfo);
-               body.setFileSize(uploadedFile.length());
+               body.setFileSize(fileSize);
                body.setOriginalFilename(name);
-               body.setStoredFilePath(uploadedFile.getAbsolutePath());
+               body.setStoredFilePath(filePath);
                //CLEAR OLD VERSION IF FILE IS NOT VERSIONED AND GETS UPDATED
                if(!header.isVersioned() && header.getCurrentBody() != null){
                        header.setCurrentBody(null);
@@ -2310,9 +2364,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
                                Iterator<FileBody> it = header.getBodies().iterator();
                                while(it.hasNext()){
                                        FileBody bo = it.next();
-                                       File fileContents = new File(bo.getStoredFilePath());
-                                       if (!fileContents.delete())
-                                               logger.error("Could not delete file " + bo.getStoredFilePath());
+                                       deleteActualFile(bo.getStoredFilePath());
                                        it.remove();
                                        dao.delete(bo);
                                }