2 * Copyright 2007, 2008, 2009 Electronic Business Systems Ltd.
4 * This file is part of GSS.
6 * GSS is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GSS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GSS. If not, see <http://www.gnu.org/licenses/>.
19 package gr.ebs.gss.server.ejb;
21 import static gr.ebs.gss.server.configuration.GSSConfigurationFactory.getConfiguration;
22 import gr.ebs.gss.client.exceptions.DuplicateNameException;
23 import gr.ebs.gss.client.exceptions.GSSIOException;
24 import gr.ebs.gss.client.exceptions.InsufficientPermissionsException;
25 import gr.ebs.gss.client.exceptions.InvitationUsedException;
26 import gr.ebs.gss.client.exceptions.ObjectNotFoundException;
27 import gr.ebs.gss.client.exceptions.QuotaExceededException;
28 import gr.ebs.gss.server.domain.AuditInfo;
29 import gr.ebs.gss.server.domain.FileBody;
30 import gr.ebs.gss.server.domain.FileHeader;
31 import gr.ebs.gss.server.domain.FileTag;
32 import gr.ebs.gss.server.domain.FileUploadStatus;
33 import gr.ebs.gss.server.domain.Folder;
34 import gr.ebs.gss.server.domain.Group;
35 import gr.ebs.gss.server.domain.Invitation;
36 import gr.ebs.gss.server.domain.Nonce;
37 import gr.ebs.gss.server.domain.Permission;
38 import gr.ebs.gss.server.domain.User;
39 import gr.ebs.gss.server.domain.UserClass;
40 import gr.ebs.gss.server.domain.dto.FileBodyDTO;
41 import gr.ebs.gss.server.domain.dto.FileHeaderDTO;
42 import gr.ebs.gss.server.domain.dto.FolderDTO;
43 import gr.ebs.gss.server.domain.dto.GroupDTO;
44 import gr.ebs.gss.server.domain.dto.PermissionDTO;
45 import gr.ebs.gss.server.domain.dto.StatsDTO;
46 import gr.ebs.gss.server.domain.dto.UserDTO;
49 import java.io.FileInputStream;
50 import java.io.FileNotFoundException;
51 import java.io.FileOutputStream;
52 import java.io.IOException;
53 import java.io.InputStream;
54 import java.io.StringWriter;
55 import java.io.UnsupportedEncodingException;
56 import java.util.ArrayList;
57 import java.util.Date;
58 import java.util.Iterator;
59 import java.util.LinkedHashSet;
60 import java.util.LinkedList;
61 import java.util.List;
62 import java.util.Locale;
63 import java.util.Random;
65 import java.util.StringTokenizer;
68 import javax.ejb.EJBException;
69 import javax.ejb.EJBTransactionRolledbackException;
70 import javax.ejb.Stateless;
71 import javax.ejb.TransactionAttribute;
72 import javax.ejb.TransactionAttributeType;
73 import javax.jms.Connection;
74 import javax.jms.ConnectionFactory;
75 import javax.jms.JMSException;
76 import javax.jms.MapMessage;
77 import javax.jms.MessageProducer;
78 import javax.jms.Queue;
79 import javax.jms.QueueConnectionFactory;
80 import javax.jms.Session;
81 import javax.naming.Context;
82 import javax.naming.InitialContext;
83 import javax.naming.NamingException;
84 import javax.persistence.PersistenceException;
85 import javax.xml.parsers.DocumentBuilder;
86 import javax.xml.parsers.DocumentBuilderFactory;
87 import javax.xml.parsers.ParserConfigurationException;
88 import javax.xml.transform.OutputKeys;
89 import javax.xml.transform.Transformer;
90 import javax.xml.transform.TransformerConfigurationException;
91 import javax.xml.transform.TransformerException;
92 import javax.xml.transform.TransformerFactory;
93 import javax.xml.transform.dom.DOMSource;
94 import javax.xml.transform.stream.StreamResult;
96 import org.apache.commons.httpclient.HttpClient;
97 import org.apache.commons.httpclient.HttpException;
98 import org.apache.commons.httpclient.NameValuePair;
99 import org.apache.commons.httpclient.methods.GetMethod;
100 import org.apache.commons.httpclient.methods.PostMethod;
101 import org.apache.commons.httpclient.methods.StringRequestEntity;
102 import org.apache.commons.lang.StringUtils;
103 import org.apache.commons.logging.Log;
104 import org.apache.commons.logging.LogFactory;
105 import org.hibernate.exception.ConstraintViolationException;
106 import org.w3c.dom.DOMException;
107 import org.w3c.dom.Document;
108 import org.w3c.dom.Node;
109 import org.w3c.dom.NodeList;
110 import org.xml.sax.SAXException;
112 import com.novell.ldap.LDAPAttribute;
113 import com.novell.ldap.LDAPAttributeSet;
114 import com.novell.ldap.LDAPConnection;
115 import com.novell.ldap.LDAPEntry;
116 import com.novell.ldap.LDAPException;
119 * The concrete implementation of the ExternalAPI interface.
124 public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
126 * The default MIME type for files without an explicit one.
128 private static final String DEFAULT_MIME_TYPE = "application/octet-stream";
131 * The size of the buffer that is used to temporarily store chunks of
132 * uploaded files, while storing them to the file repository.
134 private static final int UPLOAD_BUFFER_SIZE = 1024 * 4;
139 private static Log logger = LogFactory.getLog(ExternalAPIBean.class);
142 * Injected reference to the GSSDAO data access facade.
149 * A cached random number generator for creating unique filenames.
151 private static Random random = new Random();
154 * Mark the folder and all of its parent folders as modified from the specified user.
156 private void touchParentFolders(Folder folder, User user, Date date) {
159 AuditInfo ai = f.getAuditInfo();
160 ai.setModifiedBy(user);
161 ai.setModificationDate(date);
168 public FolderDTO getRootFolder(Long userId) throws ObjectNotFoundException {
170 throw new ObjectNotFoundException("No user specified");
171 Folder folder = dao.getRootFolder(userId);
172 return folder.getDTO();
176 public FolderDTO getFolder(final Long userId, final Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
178 throw new ObjectNotFoundException("No user specified");
179 if (folderId == null)
180 throw new ObjectNotFoundException("No folder specified");
181 final User user = dao.getEntityById(User.class, userId);
182 final Folder folder = dao.getEntityById(Folder.class, folderId);
184 if (!folder.hasReadPermission(user))
185 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
186 return folder.getDTO();
190 public User getUser(Long userId) throws ObjectNotFoundException {
192 throw new ObjectNotFoundException("No user specified");
193 return dao.getEntityById(User.class, userId);
197 public UserDTO getUserDTO(final Long userId) throws ObjectNotFoundException {
198 return getUser(userId).getDTO();
202 public GroupDTO getGroup(final Long groupId) throws ObjectNotFoundException {
204 throw new ObjectNotFoundException("No group specified");
205 final Group group = dao.getEntityById(Group.class, groupId);
206 return group.getDTO();
210 public GroupDTO getGroup(Long userId, String name) throws ObjectNotFoundException {
212 throw new ObjectNotFoundException("No user specified");
214 throw new ObjectNotFoundException("No group specified");
215 User user = dao.getEntityById(User.class, userId);
216 List<Group> groups = user.getGroupsSpecified();
217 for (Group group: groups)
218 if (group.getName().equals(name))
219 return group.getDTO();
220 throw new ObjectNotFoundException("Group " + name + " not found");
224 public List<GroupDTO> getGroups(final Long userId) throws ObjectNotFoundException {
226 throw new ObjectNotFoundException("No user specified");
227 final List<Group> groups = dao.getGroups(userId);
228 final List<GroupDTO> result = new ArrayList<GroupDTO>();
229 for (final Group g : groups)
230 result.add(g.getDTO());
235 public List<FileHeaderDTO> getFiles(Long userId, Long folderId, boolean ignoreDeleted)
236 throws ObjectNotFoundException, InsufficientPermissionsException {
239 throw new ObjectNotFoundException("No user specified");
240 if (folderId == null)
241 throw new ObjectNotFoundException("No folder specified");
242 User user = dao.getEntityById(User.class, userId);
243 Folder folder = dao.getEntityById(Folder.class, folderId);
244 if (!folder.hasReadPermission(user))
245 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
246 // Do the actual work.
247 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
248 List<FileHeader> files = dao.getFiles(folderId, userId, ignoreDeleted);
249 for (FileHeader f : files)
250 result.add(f.getDTO());
255 public List<UserDTO> getUsers(final Long userId, final Long groupId) throws ObjectNotFoundException {
258 throw new ObjectNotFoundException("No user specified");
260 throw new ObjectNotFoundException("No group specified");
262 // Do the actual work.
263 final List<User> users = dao.getUsers(groupId);
264 final List<UserDTO> result = new ArrayList<UserDTO>();
265 for (final User u : users)
266 result.add(u.getDTO());
271 public FolderDTO createFolder(Long userId, Long parentId, String name)
272 throws DuplicateNameException, ObjectNotFoundException, InsufficientPermissionsException {
275 throw new ObjectNotFoundException("No user specified");
276 if (StringUtils.isEmpty(name))
277 throw new ObjectNotFoundException("New folder name is empty");
278 if (parentId == null)
279 throw new ObjectNotFoundException("No parent specified");
280 if (dao.existsFolderOrFile(parentId, name))
281 throw new DuplicateNameException("A folder or file with the name '" +
282 name + "' already exists at this level");
284 User creator = dao.getEntityById(User.class, userId);
286 Folder parent = null;
288 parent = dao.getEntityById(Folder.class, parentId);
289 } catch (ObjectNotFoundException onfe) {
290 // Supply a more accurate problem description.
291 throw new ObjectNotFoundException("Parent folder not found");
293 if (!parent.hasWritePermission(creator))
294 throw new InsufficientPermissionsException("You don't have the permissions" +
295 " to write to this folder");
297 // Do the actual work.
298 return createFolder(name, parent, creator);
302 * Create a new folder with the provided name, parent and owner.
307 * @return the new folder
309 private FolderDTO createFolder(String name, Folder parent, User creator) {
310 Folder folder = new Folder();
311 folder.setName(name);
312 if (parent != null) {
313 parent.addSubfolder(folder);
314 folder.setOwner(parent.getOwner());
316 folder.setOwner(creator);
318 Date now = new Date();
319 AuditInfo auditInfo = new AuditInfo();
320 auditInfo.setCreatedBy(creator);
321 auditInfo.setCreationDate(now);
322 auditInfo.setModifiedBy(creator);
323 auditInfo.setModificationDate(now);
324 folder.setAuditInfo(auditInfo);
325 touchParentFolders(folder, auditInfo.getModifiedBy(), auditInfo.getModificationDate());
328 for (Permission p : parent.getPermissions()) {
329 Permission permission = new Permission();
330 permission.setGroup(p.getGroup());
331 permission.setUser(p.getUser());
332 permission.setRead(p.getRead());
333 permission.setWrite(p.getWrite());
334 permission.setModifyACL(p.getModifyACL());
335 folder.addPermission(permission);
338 Permission permission = new Permission();
339 permission.setUser(creator);
340 permission.setRead(true);
341 permission.setWrite(true);
342 permission.setModifyACL(true);
343 folder.addPermission(permission);
347 folder.setReadForAll(parent.isReadForAll());
350 return folder.getDTO();
354 public void deleteFolder(final Long userId, final Long folderId) throws InsufficientPermissionsException, ObjectNotFoundException {
357 throw new ObjectNotFoundException("No user specified");
358 if (folderId == null)
359 throw new ObjectNotFoundException("No folder specified");
361 // Do the actual work.
362 final Folder folder = dao.getEntityById(Folder.class, folderId);
363 final Folder parent = folder.getParent();
365 throw new ObjectNotFoundException("Deleting the root folder is not allowed");
366 final User user = dao.getEntityById(User.class, userId);
367 if (!folder.hasDeletePermission(user)) {
368 logger.info("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
369 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
371 removeSubfolderFiles(folder);
372 parent.removeSubfolder(folder);
374 touchParentFolders(parent, user, new Date());
378 * Traverses the folder and deletes all actual files (file system)
379 * regardless of permissions
383 private void removeSubfolderFiles(Folder folder) {
384 //remove files for all subfolders
385 for (Folder subfolder:folder.getSubfolders())
386 removeSubfolderFiles(subfolder);
387 //remove this folder's file bodies (actual files)
388 for (FileHeader file:folder.getFiles()) {
389 for (FileBody body:file.getBodies())
390 deleteActualFile(body.getStoredFilePath());
391 indexFile(file.getId(), true);
396 @SuppressWarnings("unchecked")
397 public List<FolderDTO> getSubfolders(Long userId, Long folderId)
398 throws ObjectNotFoundException, InsufficientPermissionsException {
400 throw new ObjectNotFoundException("No user specified");
401 if (folderId == null)
402 throw new ObjectNotFoundException("No folder specified");
403 User user = dao.getEntityById(User.class, userId);
404 Folder folder = dao.getEntityById(Folder.class, folderId);
405 if (!folder.hasReadPermission(user))
406 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
407 List<FolderDTO> result = new ArrayList<FolderDTO>();
408 if (folder.hasReadPermission(user))
409 for (Folder f : folder.getSubfolders())
410 if (f.hasReadPermission(user) && !f.isDeleted())
411 result.add(f.getDTO());
416 public FolderDTO updateFolder(Long userId, Long folderId, String folderName,
418 Set<PermissionDTO> permissions)
419 throws InsufficientPermissionsException, ObjectNotFoundException,
420 DuplicateNameException {
424 throw new ObjectNotFoundException("No user specified");
425 if (folderId == null)
426 throw new ObjectNotFoundException("No folder specified");
428 Folder folder = dao.getEntityById(Folder.class, folderId);
429 User user = dao.getEntityById(User.class, userId);
430 if (folderName != null && !folder.hasWritePermission(user))
431 throw new InsufficientPermissionsException("You don't have the necessary permissions");
432 if(permissions != null && !permissions.isEmpty() && !folder.hasModifyACLPermission(user))
433 throw new InsufficientPermissionsException("You don't have the necessary permissions");
434 // Check permissions for making file public.
435 if (readForAll != null && !user.equals(folder.getOwner()))
436 throw new InsufficientPermissionsException("Only the owner can make a folder public or not public");
438 Folder parent = folder.getParent();
439 if (folderName != null) {
441 if (!folder.getName().equals(folderName) && dao.existsFolderOrFile(parent.getId(), folderName))
442 throw new DuplicateNameException("A folder or file with the name '" + folderName + "' already exists at this level");
444 // Do the actual modification.
445 folder.setName(folderName);
447 if (permissions != null)
448 setFolderPermissions(user, folder, permissions);
449 if (readForAll != null)
450 setFolderReadForAll(user, folder, readForAll);
451 folder.getAuditInfo().setModificationDate(new Date());
452 folder.getAuditInfo().setModifiedBy(user);
454 touchParentFolders(folder, user, new Date());
455 return folder.getDTO();
459 public void createGroup(final Long userId, final String name) throws ObjectNotFoundException, DuplicateNameException {
462 throw new ObjectNotFoundException("No user specified");
463 if (StringUtils.isEmpty(name))
464 throw new ObjectNotFoundException("New group name is empty");
465 if (name.indexOf('/')>=0)
466 throw new IllegalArgumentException("Character '/' is not allowed in group name");
467 if (dao.existsGroup(userId, name))
468 throw new DuplicateNameException("A group with the name '" + name + "' already exists");
470 // TODO: Check permissions
472 final User owner = dao.getEntityById(User.class, userId);
474 // Do the actual work.
475 owner.createGroup(name);
479 public void deleteGroup(final Long userId, final Long groupId) throws ObjectNotFoundException, InsufficientPermissionsException {
482 throw new ObjectNotFoundException("No user specified");
484 throw new ObjectNotFoundException("No group specified");
486 // Do the actual work.
487 final User owner = dao.getEntityById(User.class, userId);
488 final Group group = dao.getEntityById(Group.class, groupId);
489 final Date now = new Date();
490 // Only delete the group if actually owned by the user.
491 if (group.getOwner().equals(owner)) {
492 List<Folder> folders = dao.getFoldersPermittedForGroup(userId, groupId);
493 for (Folder f : folders){
494 f.getPermissions().removeAll(group.getPermissions());
495 touchFolder(f,owner,now);
496 for(FileHeader file : f.getFiles()){
497 file.getPermissions().removeAll(group.getPermissions());
498 touchFile(file,owner,now);
501 List<FileHeader> files = dao.getSharedFilesNotInSharedFolders(userId);
502 for(FileHeader h : files){
503 h.getPermissions().removeAll(group.getPermissions());
504 touchFile(h,owner,now);
506 owner.removeSpecifiedGroup(group);
509 else throw new InsufficientPermissionsException("You are not the owner of this group");
513 public FileHeaderDTO createFile(Long userId, Long folderId, String name, String mimeType, InputStream stream)
514 throws DuplicateNameException, ObjectNotFoundException, GSSIOException,
515 InsufficientPermissionsException, QuotaExceededException {
518 file = uploadFile(stream, userId);
519 } catch ( IOException ioe) {
520 // Supply a more accurate problem description.
521 throw new GSSIOException("Problem creating file",ioe);
523 return createFile(userId, folderId, name, mimeType, file.length(), file.getAbsolutePath());
527 * @see gr.ebs.gss.server.ejb.ExternalAPIRemote#indexFile(java.lang.Long, boolean)
530 public void indexFile(Long fileId, boolean delete) {
531 Connection qConn = null;
532 Session session = null;
533 MessageProducer sender = null;
535 Context jndiCtx = new InitialContext();
536 ConnectionFactory factory = (QueueConnectionFactory) jndiCtx.lookup("java:/JmsXA");
537 Queue queue = (Queue) jndiCtx.lookup("queue/gss-indexingQueue");
538 qConn = factory.createConnection();
539 session = qConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
540 sender = session.createProducer(queue);
542 MapMessage map = session.createMapMessage();
543 map.setObject("id", fileId);
544 map.setBoolean("delete", delete);
547 catch (NamingException e) {
548 logger.error("Index was not updated: ", e);
550 catch (JMSException e) {
551 logger.error("Index was not updated: ", e);
562 catch (JMSException e) {
571 * A helper method that generates a unique file path for a stored file. The
572 * files are stored using random hash names that are distributed evenly in
573 * a 2-level tree of subdirectories named after the first two hex characters
574 * in the name. For example, file ab1234cd5769f will be stored in the path
575 * /file-repository-root/a/b/ab1234cd5769f. The directories will be created
576 * if they don't already exist.
578 * @return a unique new file path
580 private String generateRepositoryFilePath() {
581 String filename = Long.toHexString(random.nextLong());
582 String fileRepositoryPath = getConfiguration().getString("fileRepositoryPath","/tmp");
583 File root = new File(fileRepositoryPath);
586 File firstFolder = new File(root + File.separator + filename.substring(0, 1));
587 if (!firstFolder.exists())
589 File secondFolder = new File(firstFolder + File.separator + filename.substring(1, 2));
590 if (!secondFolder.exists())
591 secondFolder.mkdir();
592 return secondFolder + File.separator + filename;
596 public void deleteFile(final Long userId, final Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
599 throw new ObjectNotFoundException("No user specified");
601 throw new ObjectNotFoundException("No file specified");
603 // Do the actual work.
604 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
605 final Folder parent = file.getFolder();
607 throw new ObjectNotFoundException("The specified file has no parent folder");
608 final User user = dao.getEntityById(User.class, userId);
609 if (!file.hasDeletePermission(user))
610 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
611 for (final FileBody body : file.getBodies())
612 deleteActualFile(body.getStoredFilePath());
614 touchParentFolders(parent, user, new Date());
615 indexFile(fileId, true);
619 public void deleteActualFile(String path) {
622 File file = new File(path);
624 logger.error("Could not delete file " + path);
628 public void createTag(final Long userId, final Long fileHeaderId, final String tag) throws ObjectNotFoundException {
630 throw new ObjectNotFoundException("No user specified");
631 if (fileHeaderId == null)
632 throw new ObjectNotFoundException("No file specified");
633 if (StringUtils.isEmpty(tag))
634 throw new ObjectNotFoundException("Tag is empty");
636 final User user = dao.getEntityById(User.class, userId);
637 final FileHeader fh = dao.getEntityById(FileHeader.class, fileHeaderId);
638 final Folder parent = fh.getFolder();
640 throw new ObjectNotFoundException("The specified file has no parent folder");
641 user.addTag(fh, tag);
642 touchParentFolders(parent, user, new Date());
646 public Set<String> getUserTags(final Long userId) throws ObjectNotFoundException {
647 return dao.getUserTags(userId);
651 public void updateFile(Long userId, Long fileId, String name,
652 String tagSet, Date modificationDate, Boolean versioned,
653 Boolean readForAll, Set<PermissionDTO> permissions)
654 throws DuplicateNameException, ObjectNotFoundException, InsufficientPermissionsException {
656 throw new ObjectNotFoundException("No user specified");
658 throw new ObjectNotFoundException("No file specified");
659 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
660 final Folder parent = file.getFolder();
662 throw new ObjectNotFoundException("The specified file has no parent folder");
664 User user = dao.getEntityById(User.class, userId);
665 // Check permissions for modifying the file metadata.
666 if ((name != null || tagSet != null || modificationDate != null || versioned != null) && !file.hasWritePermission(user))
667 throw new InsufficientPermissionsException("User " + user.getId() + " cannot update file " + file.getName() + "(" + file.getId() + ")");
668 // Check permissions for making file public.
669 if (readForAll != null && !user.equals(file.getOwner()))
670 throw new InsufficientPermissionsException("Only the owner can make a file public or not public");
671 // Check permissions for modifying the ACL.
672 if(permissions != null && !permissions.isEmpty() && !file.hasModifyACLPermission(user))
673 throw new InsufficientPermissionsException("User " + user.getId() + " cannot update the permissions on file " + file.getName() + "(" + file.getId() + ")");
676 // Do plain check for file already exists.
677 // Extreme concurrency case should be caught by constraint violation later.
678 if (dao.existsFolderOrFile(parent.getId(), name)) throw new DuplicateNameException("A file or folder with the name '" + name + "' already exists");
682 if (modificationDate != null)
683 file.getAuditInfo().setModificationDate(modificationDate);
685 file.getAuditInfo().setModificationDate(new Date());
686 file.getAuditInfo().setModifiedBy(user);
688 List<FileTag> tags = file.getFileTags();
689 if (tagSet != null) {
690 Iterator<FileTag> i = tags.iterator();
691 while (i.hasNext()) {
692 FileTag tag = i.next();
699 StringTokenizer st = new StringTokenizer(tagSet, ",");
700 while (st.hasMoreTokens())
701 new FileTag(user, file, st.nextToken().trim());
703 if (versioned != null && !file.isVersioned() == versioned) {
704 if (file.isVersioned())
705 removeOldVersions(userId, fileId);
706 file.setVersioned(versioned);
708 if (readForAll == null)
709 throw new ObjectNotFoundException("The 'public' value for the specific file hasn't been specified");
710 if (user.equals(file.getOwner()))
711 file.setReadForAll(readForAll);
712 if (permissions != null && !permissions.isEmpty())
713 setFilePermissions(file, permissions);
716 * Force constraint violation to manifest itself here.
717 * This should cover extreme concurrency cases that the simple check
718 * above hasn't caught.
723 catch (EJBTransactionRolledbackException e) {
724 Throwable cause = e.getCause();
725 if (cause instanceof PersistenceException && cause.getCause() instanceof ConstraintViolationException)
726 throw new DuplicateNameException("A file or folder with the name '" + name + "' already exists");
730 touchParentFolders(parent, user, new Date());
732 // Re-index the file if it was modified.
733 if (name != null || tagSet != null)
734 indexFile(fileId, false);
738 public InputStream getFileContents(Long userId, Long fileId)
739 throws ObjectNotFoundException, InsufficientPermissionsException {
741 throw new ObjectNotFoundException("No user specified");
743 throw new ObjectNotFoundException("No file specified");
745 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
746 User user = dao.getEntityById(User.class, userId);
747 if (!header.hasReadPermission(user)) {
748 logger.info("User " + user.getId() + " cannot read file " + header.getName() + "(" + fileId + ")");
749 throw new InsufficientPermissionsException("You don't have the necessary permissions");
752 File f = new File(header.getCurrentBody().getStoredFilePath());
754 return new FileInputStream(f);
755 } catch (FileNotFoundException e) {
756 logger.error("Could not locate the contents of file " + f.getAbsolutePath());
757 throw new ObjectNotFoundException("The file contents could not be located");
762 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFileContents(java.lang.Long, java.lang.Long, java.lang.Long)
765 public InputStream getFileContents(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
767 throw new ObjectNotFoundException("No user specified");
769 throw new ObjectNotFoundException("No file specified");
771 throw new ObjectNotFoundException("No file specified");
773 final FileHeader header = dao.getEntityById(FileHeader.class, fileId);
774 final FileBody body = dao.getEntityById(FileBody.class, bodyId);
775 final User user = dao.getEntityById(User.class, userId);
776 if (!header.hasReadPermission(user)) {
777 logger.info("User " + user.getId() + " cannot read file " + header.getName() + "(" + fileId + ")");
778 throw new InsufficientPermissionsException("You don't have the necessary permissions");
781 File f = new File(body.getStoredFilePath());
783 return new FileInputStream(f);
784 } catch (FileNotFoundException e) {
785 logger.error("Could not locate the contents of file " + f.getAbsolutePath());
786 throw new ObjectNotFoundException("The file contents could not be located");
791 public FileHeaderDTO getFile(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
793 throw new ObjectNotFoundException("No user specified");
795 throw new ObjectNotFoundException("No file specified");
796 final User user = dao.getEntityById(User.class, userId);
797 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
798 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
799 throw new InsufficientPermissionsException("You don't have the necessary permissions");
800 return file.getDTO();
804 public FileBodyDTO getFileBody(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
806 throw new ObjectNotFoundException("No user specified");
808 throw new ObjectNotFoundException("No file specified");
809 User user = dao.getEntityById(User.class, userId);
810 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
811 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
812 throw new InsufficientPermissionsException("You don't have the necessary permissions");
813 FileBody body = dao.getEntityById(FileBody.class, bodyId);
814 return body.getDTO();
818 public Object getResourceAtPath(Long ownerId, String path, boolean ignoreDeleted)
819 throws ObjectNotFoundException {
821 throw new ObjectNotFoundException("No user specified");
822 if (StringUtils.isEmpty(path))
823 throw new ObjectNotFoundException("No path specified");
825 User owner = dao.getEntityById(User.class, ownerId);
826 List<String> pathElements = new ArrayList<String>();
827 StringTokenizer st = new StringTokenizer(path, "/");
828 while (st.hasMoreTokens())
829 pathElements.add(st.nextToken());
830 if (pathElements.size() < 1)
831 return getRootFolder(owner.getId());
832 // Store the last element, since it requires special handling.
833 String lastElement = pathElements.remove(pathElements.size() - 1);
834 FolderDTO cursor = getRootFolder(owner.getId());
835 // Traverse and verify the specified folder path.
836 for (String pathElement : pathElements) {
837 cursor = getFolder(cursor.getId(), pathElement);
838 if (cursor.isDeleted())
839 throw new ObjectNotFoundException("Folder " + cursor.getPath() + " not found");
842 // Use the lastElement to retrieve the actual resource.
843 Object resource = null;
845 FileHeaderDTO file = getFile(cursor.getId(), lastElement);
846 if (ignoreDeleted && file.isDeleted())
847 throw new ObjectNotFoundException("Resource not found");
849 } catch (ObjectNotFoundException e) {
850 // Perhaps the requested resource is not a file, so
851 // check for folders as well.
852 FolderDTO folder = getFolder(cursor.getId(), lastElement);
853 if (ignoreDeleted && folder.isDeleted())
854 throw new ObjectNotFoundException("Resource not found");
861 * Retrieve a file for the specified user that has the specified name and
862 * its parent folder has id equal to folderId.
864 * @param userId the ID of the current user
865 * @param folderId the ID of the parent folder
866 * @param name the name of the requested file
867 * @return the file found
868 * @throws ObjectNotFoundException if the specified folder or file was not
869 * found, with the exception message mentioning the precise
872 private FileHeaderDTO getFile(Long folderId, String name) throws ObjectNotFoundException {
873 if (folderId == null)
874 throw new ObjectNotFoundException("No parent folder specified");
875 if (StringUtils.isEmpty(name))
876 throw new ObjectNotFoundException("No file specified");
878 FileHeader file = dao.getFile(folderId, name);
879 return file.getDTO();
883 * Retrieve a folder for the specified user that has the specified name and
884 * its parent folder has id equal to parentId.
886 * @param parentId the ID of the parent folder
887 * @param name the name of the requested folder
888 * @return the folder found
889 * @throws ObjectNotFoundException if the specified folder or parent was not
890 * found, with the exception message mentioning the precise
893 private FolderDTO getFolder(Long parentId, String name) throws ObjectNotFoundException {
894 if (parentId == null)
895 throw new ObjectNotFoundException("No parent folder specified");
896 if (StringUtils.isEmpty(name))
897 throw new ObjectNotFoundException("No folder specified");
899 Folder folder = dao.getFolder(parentId, name);
900 return folder.getDTO();
903 private FileHeaderDTO updateFileContents(Long userId, Long fileId, String mimeType, InputStream resourceInputStream) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
906 file = uploadFile(resourceInputStream, userId);
907 } catch ( IOException ioe) {
908 // Supply a more accurate problem description.
909 throw new GSSIOException("Problem creating file",ioe);
911 return updateFileContents(userId, fileId, mimeType, file.length(), file.getAbsolutePath());
915 public void copyFile(Long userId, Long fileId, String dest) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
917 throw new ObjectNotFoundException("No user specified");
919 throw new ObjectNotFoundException("No file specified");
920 if (StringUtils.isEmpty(dest))
921 throw new ObjectNotFoundException("No destination specified");
923 Object destination = getResourceAtPath(userId, getParentPath(dest), true);
924 if (!(destination instanceof FolderDTO))
925 throw new ObjectNotFoundException("Destination parent folder not found");
926 FolderDTO parent = (FolderDTO) destination;
927 copyFile(userId, fileId, parent.getId(), getLastElement(dest));
931 public void copyFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
933 throw new ObjectNotFoundException("No user specified");
935 throw new ObjectNotFoundException("No owner specified");
937 throw new ObjectNotFoundException("No file specified");
938 if (StringUtils.isEmpty(dest))
939 throw new ObjectNotFoundException("No destination specified");
941 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
942 if (!(destination instanceof FolderDTO))
943 throw new ObjectNotFoundException("Destination parent folder not found");
944 FolderDTO parent = (FolderDTO) destination;
945 copyFile(userId, fileId, parent.getId(), getLastElement(dest));
949 public void copyFile(Long userId, Long fileId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
951 throw new ObjectNotFoundException("No user specified");
953 throw new ObjectNotFoundException("No file specified");
955 throw new ObjectNotFoundException("No destination specified");
956 if (StringUtils.isEmpty(destName))
957 throw new ObjectNotFoundException("No destination file name specified");
959 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
960 Folder destination = dao.getEntityById(Folder.class, destId);
961 User user = dao.getEntityById(User.class, userId);
962 if (!file.hasReadPermission(user) || !destination.hasWritePermission(user))
963 throw new InsufficientPermissionsException("You don't have the necessary permissions");
964 boolean versioned = file.isVersioned();
965 int versionsNumber = file.getBodies().size();
966 FileBody oldestBody = file.getBodies().get(0);
967 assert oldestBody != null;
968 File contents = new File(oldestBody.getStoredFilePath());
970 createFile(user.getId(), destination.getId(), destName, oldestBody.getMimeType(), new FileInputStream(contents));
971 FileHeader copiedFile = dao.getFile(destination.getId(), destName);
972 copiedFile.setVersioned(versioned);
974 if (versionsNumber > 1)
975 for (int i = 1; i < versionsNumber; i++) {
976 FileBody body = file.getBodies().get(i);
978 contents = new File(body.getStoredFilePath());
979 updateFileContents(user.getId(), copiedFile.getId(), body.getMimeType(), new FileInputStream(contents));
981 List<FileTag> tags = file.getFileTags();
982 for (FileTag tag : tags)
983 createTag(userId, copiedFile.getId(), tag.getTag());
985 } catch (FileNotFoundException e) {
986 throw new ObjectNotFoundException("File contents not found for file " + contents.getAbsolutePath());
992 public void copyFolder(Long userId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
994 throw new ObjectNotFoundException("No user specified");
995 if (folderId == null)
996 throw new ObjectNotFoundException("No folder specified");
997 if (StringUtils.isEmpty(dest))
998 throw new ObjectNotFoundException("No destination specified");
1000 Object destination = getResourceAtPath(userId, getParentPath(dest), true);
1001 if (!(destination instanceof FolderDTO))
1002 throw new ObjectNotFoundException("Destination folder not found");
1003 FolderDTO parent = (FolderDTO) destination;
1004 copyFolder(userId, folderId, parent.getId(), getLastElement(dest));
1008 public void copyFolder(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
1010 throw new ObjectNotFoundException("No user specified");
1011 if (folderId == null)
1012 throw new ObjectNotFoundException("No folder specified");
1014 throw new ObjectNotFoundException("No destination specified");
1015 if (StringUtils.isEmpty(destName))
1016 throw new ObjectNotFoundException("No destination folder name specified");
1017 Folder folder = dao.getEntityById(Folder.class, folderId);
1018 Folder destination = dao.getEntityById(Folder.class, destId);
1019 User user = dao.getEntityById(User.class, userId);
1020 if (!destination.hasWritePermission(user) || !folder.hasReadPermission(user))
1021 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1022 createFolder(user.getId(), destination.getId(), destName);
1026 public void copyFolderStructureToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1028 throw new ObjectNotFoundException("No user specified");
1029 if (ownerId == null)
1030 throw new ObjectNotFoundException("No owner specified");
1031 if (folderId == null)
1032 throw new ObjectNotFoundException("No folder specified");
1033 if (StringUtils.isEmpty(dest))
1034 throw new ObjectNotFoundException("No destination specified");
1036 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1037 if (!(destination instanceof FolderDTO))
1038 throw new ObjectNotFoundException("Destination folder not found");
1039 FolderDTO parent = (FolderDTO) destination;
1040 copyFolderStructure(userId, folderId, parent.getId(), getLastElement(dest));
1044 public void copyFolderStructure(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1046 throw new ObjectNotFoundException("No user specified");
1047 if (folderId == null)
1048 throw new ObjectNotFoundException("No folder specified");
1050 throw new ObjectNotFoundException("No destination specified");
1051 if (StringUtils.isEmpty(destName))
1052 throw new ObjectNotFoundException("No destination folder name specified");
1054 Folder folder = dao.getEntityById(Folder.class, folderId);
1055 Folder destination = dao.getEntityById(Folder.class, destId);
1056 final User user = dao.getEntityById(User.class, userId);
1057 // XXX: quick fix need to copy only visible items to user (Source
1059 if (!folder.getOwner().getId().equals(userId) && !folder.hasReadPermission(user))
1061 if(folder.isDeleted())//do not copy trashed folder and contents
1063 if (!destination.hasWritePermission(user) || !folder.hasReadPermission(user))
1064 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1065 createFolder(user.getId(), destination.getId(), destName);
1066 Folder createdFolder = dao.getFolder(destination.getId(), destName);
1067 List<FileHeader> files = folder.getFiles();
1069 for (FileHeader file : files)
1070 if(!file.isDeleted())
1071 copyFile(userId, file.getId(), createdFolder.getId(), file.getName());
1072 List<Folder> subFolders = folder.getSubfolders();
1073 if (subFolders != null)
1074 for (Folder sub : subFolders)
1075 if(!sub.getId().equals(createdFolder.getId()))
1076 copyFolderStructure(userId, sub.getId(), createdFolder.getId(), sub.getName());
1081 * For a provided path, remove the last element and return the rest, that is
1082 * the path of the parent folder.
1084 * @param path the specified path
1085 * @return the path of the parent folder
1086 * @throws ObjectNotFoundException if the provided string contains no path
1089 private String getParentPath(String path) throws ObjectNotFoundException {
1090 int lastDelimiter = path.lastIndexOf('/');
1091 if (lastDelimiter == 0)
1093 if (lastDelimiter == -1)
1095 throw new ObjectNotFoundException("There is no parent in the path: " + path);
1096 else if (lastDelimiter < path.length() - 1)
1097 // Return the part before the delimiter.
1098 return path.substring(0, lastDelimiter);
1100 // Remove the trailing delimiter and then recurse.
1101 String strippedTrail = path.substring(0, lastDelimiter);
1102 return getParentPath(strippedTrail);
1107 * Get the last element in a path that denotes the file or folder name.
1109 * @param path the provided path
1110 * @return the last element in the path
1112 private String getLastElement(String path) {
1113 int lastDelimiter = path.lastIndexOf('/');
1114 if (lastDelimiter == -1)
1117 else if (lastDelimiter < path.length() - 1)
1118 // Return the part after the delimiter.
1119 return path.substring(lastDelimiter + 1);
1121 // Remove the trailing delimiter and then recurse.
1122 String strippedTrail = path.substring(0, lastDelimiter);
1123 return getLastElement(strippedTrail);
1128 public void moveFileToTrash(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1130 throw new ObjectNotFoundException("No user specified");
1132 throw new ObjectNotFoundException("No file specified");
1134 // Do the actual work.
1135 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1136 Folder parent = file.getFolder();
1138 throw new ObjectNotFoundException("The specified file has no parent folder");
1139 User user = dao.getEntityById(User.class, userId);
1140 if (!file.hasDeletePermission(user))
1141 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
1143 file.setDeleted(true);
1145 touchParentFolders(parent, user, new Date());
1149 public void moveFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, InsufficientPermissionsException, QuotaExceededException {
1151 throw new ObjectNotFoundException("No user specified");
1152 if (ownerId == null)
1153 throw new ObjectNotFoundException("No owner specified");
1155 throw new ObjectNotFoundException("No file specified");
1156 if (StringUtils.isEmpty(dest))
1157 throw new ObjectNotFoundException("No destination specified");
1159 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1160 if (!(destination instanceof FolderDTO))
1161 throw new ObjectNotFoundException("Destination parent folder not found");
1162 FolderDTO parent = (FolderDTO) destination;
1163 moveFile(userId, fileId, parent.getId(), getLastElement(dest));
1167 public void moveFile(Long userId, Long fileId, Long destId, String destName) throws InsufficientPermissionsException, ObjectNotFoundException, QuotaExceededException {
1169 throw new ObjectNotFoundException("No user specified");
1171 throw new ObjectNotFoundException("No file specified");
1173 throw new ObjectNotFoundException("No destination specified");
1174 if (StringUtils.isEmpty(destName))
1175 throw new ObjectNotFoundException("No destination file name specified");
1177 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1178 Folder source = file.getFolder();
1179 Folder destination = dao.getEntityById(Folder.class, destId);
1181 User owner = dao.getEntityById(User.class, userId);
1182 if (!file.hasDeletePermission(owner) || !destination.hasWritePermission(owner))
1183 throw new InsufficientPermissionsException("User " + owner.getId() + " cannot move file " + file.getName() + "(" + file.getId() + ")");
1185 // if the destination folder belongs to another user:
1186 if (!file.getOwner().equals(destination.getOwner())) {
1187 // (a) check if the destination quota allows the move
1188 if(getQuotaLeft(destination.getOwner().getId()) < file.getTotalSize())
1189 throw new QuotaExceededException("Not enough free space available");
1190 User newOwner = destination.getOwner();
1191 // (b) if quota OK, change the owner of the file
1192 file.setOwner(newOwner);
1193 // if the file has no permission for the new owner, add it
1194 Permission ownerPermission = null;
1195 for (final Permission p : file.getPermissions())
1196 if (p.getUser() != null)
1197 if (p.getUser().equals(newOwner)) {
1198 ownerPermission = p;
1201 if (ownerPermission == null) {
1202 ownerPermission = new Permission();
1203 ownerPermission.setUser(newOwner);
1204 file.addPermission(ownerPermission);
1206 ownerPermission.setRead(true);
1207 ownerPermission.setWrite(true);
1208 ownerPermission.setModifyACL(true);
1210 // move the file to the destination folder
1211 file.setFolder(destination);
1212 touchParentFolders(source, owner, new Date());
1213 touchParentFolders(destination, owner, new Date());
1217 public void moveFolderToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, InsufficientPermissionsException, QuotaExceededException {
1219 throw new ObjectNotFoundException("No user specified");
1220 if (ownerId == null)
1221 throw new ObjectNotFoundException("No owner specified");
1222 if (folderId == null)
1223 throw new ObjectNotFoundException("No folder specified");
1224 if (StringUtils.isEmpty(dest))
1225 throw new ObjectNotFoundException("No destination specified");
1227 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1228 if (!(destination instanceof FolderDTO))
1229 throw new ObjectNotFoundException("Destination parent folder not found");
1230 FolderDTO parent = (FolderDTO) destination;
1231 moveFolder(userId, folderId, parent.getId(), getLastElement(dest));
1235 public void moveFolder(Long userId, Long folderId, Long destId, String destName)
1236 throws ObjectNotFoundException, InsufficientPermissionsException,
1237 QuotaExceededException {
1238 Folder source = dao.getEntityById(Folder.class, folderId);
1239 Folder destination = dao.getEntityById(Folder.class, destId);
1240 User user = dao.getEntityById(User.class, userId);
1241 User sourceOwner = source.getOwner();
1242 User destinationOwner = destination.getOwner();
1243 // Do not move trashed folders and contents.
1244 if (source.isDeleted())
1246 // Check permissions.
1247 if (!destination.hasWritePermission(user)
1248 || !source.hasReadPermission(user)
1249 || !source.hasWritePermission(user))
1250 throw new InsufficientPermissionsException("You don't have the " +
1251 "necessary permissions");
1252 // Use the same timestamp for all subsequent modifications to make
1253 // changes appear simultaneous.
1254 Date now = new Date();
1255 // If source and destination are not in the same user's namespace,
1256 // change owners and check quota.
1257 if (!sourceOwner.equals(destinationOwner)) {
1258 changeOwner(source, destinationOwner, user, now);
1259 if (getQuotaLeft(destinationOwner.getId()) < 0)
1260 throw new QuotaExceededException("Not enough free space " +
1261 "available in destination folder");
1263 // Perform the move.
1264 Folder oldParent = source.getParent();
1265 oldParent.removeSubfolder(source);
1266 destination.addSubfolder(source);
1267 // Mark the former parent and destination trees upwards as modified.
1268 touchParentFolders(oldParent, user, now);
1269 touchParentFolders(source, user, now);
1273 * Recursively change the owner of the specified folder and all of its
1274 * contents to the specified owner. Also mark them all as modified with the
1275 * specified modifier and modificationDate.
1277 private void changeOwner(Folder folder, User owner, User modifier, Date modificationDate) {
1278 for (FileHeader file: folder.getFiles()) {
1279 file.setOwner(owner);
1280 file.getAuditInfo().setModificationDate(modificationDate);
1281 file.getAuditInfo().setModifiedBy(modifier);
1283 for (Folder sub: folder.getSubfolders())
1284 changeOwner(sub, owner, modifier, modificationDate);
1285 folder.setOwner(owner);
1286 folder.getAuditInfo().setModificationDate(modificationDate);
1287 folder.getAuditInfo().setModifiedBy(modifier);
1291 public List<FileHeaderDTO> getDeletedFiles(Long userId) throws ObjectNotFoundException {
1294 throw new ObjectNotFoundException("No user specified");
1296 // Do the actual work.
1297 final List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1298 final List<FileHeader> files = dao.getDeletedFiles(userId);
1299 for (final FileHeader f : files)
1300 result.add(f.getDTO());
1305 public void removeFileFromTrash(Long userId, Long fileId)
1306 throws ObjectNotFoundException, InsufficientPermissionsException {
1308 throw new ObjectNotFoundException("No user specified");
1310 throw new ObjectNotFoundException("No file specified");
1312 // Do the actual work.
1313 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1314 Folder parent = file.getFolder();
1316 throw new ObjectNotFoundException("The specified file has no parent folder");
1317 User user = dao.getEntityById(User.class, userId);
1318 if (!file.hasDeletePermission(user))
1319 throw new InsufficientPermissionsException("User " + user.getUsername() +
1320 " cannot restore file " + file.getName());
1322 file.setDeleted(false);
1324 touchParentFolders(parent, user, new Date());
1328 public void moveFolderToTrash(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
1330 throw new ObjectNotFoundException("No user specified");
1331 if (folderId == null)
1332 throw new ObjectNotFoundException("No folder specified");
1333 Folder folder = dao.getEntityById(Folder.class, folderId);
1334 User user = dao.getEntityById(User.class, userId);
1335 if (!folder.hasDeletePermission(user))
1336 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1337 folder.setDeleted(true);
1339 touchParentFolders(folder, user, new Date());
1340 for (FileHeader file : folder.getFiles())
1341 moveFileToTrash(userId, file.getId());
1342 for (Folder subFolder : folder.getSubfolders())
1343 moveFolderToTrash(userId, subFolder.getId());
1348 public void removeFolderFromTrash(Long userId, Long folderId)
1349 throws ObjectNotFoundException, InsufficientPermissionsException {
1351 throw new ObjectNotFoundException("No user specified");
1352 if (folderId == null)
1353 throw new ObjectNotFoundException("No folder specified");
1354 Folder folder = dao.getEntityById(Folder.class, folderId);
1355 User user = dao.getEntityById(User.class, userId);
1356 if (!folder.hasDeletePermission(user))
1357 throw new InsufficientPermissionsException("User " + user.getUsername() +
1358 " cannot restore folder " + folder.getName());
1359 folder.setDeleted(false);
1360 for (FileHeader file : folder.getFiles())
1361 removeFileFromTrash(userId, file.getId());
1362 for (Folder subFolder : folder.getSubfolders())
1363 removeFolderFromTrash(userId, subFolder.getId());
1365 touchParentFolders(folder, user, new Date());
1369 public List<FolderDTO> getDeletedRootFolders(Long userId) throws ObjectNotFoundException {
1370 List<Folder> folders = dao.getDeletedRootFolders(userId);
1371 List<FolderDTO> result = new ArrayList<FolderDTO>();
1372 for (Folder folder : folders)
1373 result.add(folder.getDTO());
1378 public void emptyTrash(Long userId) throws ObjectNotFoundException, InsufficientPermissionsException {
1379 List<FolderDTO> deletedRootFolders = getDeletedRootFolders(userId);
1380 for (FolderDTO fdto : deletedRootFolders)
1381 deleteFolder(userId, fdto.getId());
1382 List<FileHeaderDTO> deletedFiles = getDeletedFiles(userId);
1383 for (FileHeaderDTO filedto : deletedFiles)
1384 deleteFile(userId, filedto.getId());
1388 public void restoreTrash(Long userId) throws ObjectNotFoundException, InsufficientPermissionsException {
1389 List<FolderDTO> deletedRootFolders = getDeletedRootFolders(userId);
1390 for (FolderDTO fdto : deletedRootFolders)
1391 removeFolderFromTrash(userId, fdto.getId());
1392 List<FileHeaderDTO> deletedFiles = getDeletedFiles(userId);
1393 for (FileHeaderDTO filedto : deletedFiles)
1394 removeFileFromTrash(userId, filedto.getId());
1398 public User createUser(String username, String name, String mail,
1399 String idp, String idpid) throws ObjectNotFoundException {
1400 if (username == null)
1401 throw new ObjectNotFoundException("No username specified");
1403 throw new ObjectNotFoundException("No name specified");
1405 User user = new User();
1406 user.setUsername(username);
1408 user.setEmail(mail);
1409 user.setIdentityProvider(idp);
1410 user.setIdentityProviderId(idpid);
1411 Date now = new Date();
1412 AuditInfo auditInfo = new AuditInfo();
1413 auditInfo.setCreationDate(now);
1414 auditInfo.setModificationDate(now);
1415 user.setAuditInfo(auditInfo);
1416 user.setActive(true);
1417 user.generateAuthToken();
1418 user.generateWebDAVPassword();
1419 user.setUserClass(getDefaultUserClass());
1421 // Make sure we get an ID in the user object.
1423 // Create the root folder for the user.
1424 createFolder(user.getName(), null, user);
1429 * Get the default user class, which is the one with the lowest quota.
1431 private UserClass getDefaultUserClass() {
1432 return getUserClasses().get(0);
1436 public List<UserClass> getUserClasses() {
1437 List<UserClass> classes = dao.getUserClasses();
1438 // Create a default user class for first-time use. Afterwards, the
1439 // admin should modify or add to the userclass table.
1440 if (classes.size() == 0) {
1441 UserClass defaultClass = new UserClass();
1442 defaultClass.setName("default");
1443 Long defaultQuota = getConfiguration().getLong("quota", new Long(52428800L));
1444 defaultClass.setQuota(defaultQuota);
1445 dao.create(defaultClass);
1446 classes.add(defaultClass);
1452 public User findUserByEmail(String email) {
1453 return dao.findUserByEmail(email);
1457 public void updateUser(User user) {
1462 public User findUser(String username) {
1463 if (username == null)
1465 return dao.findUser(username);
1469 public User updateUserToken(Long userId) throws ObjectNotFoundException {
1471 throw new ObjectNotFoundException("No user specified");
1472 User user = dao.getEntityById(User.class, userId);
1473 user.generateAuthToken();
1478 public Set<PermissionDTO> getFolderPermissions(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
1480 throw new ObjectNotFoundException("No user specified");
1481 if (folderId == null)
1482 throw new ObjectNotFoundException("No folder specified");
1483 User user = dao.getEntityById(User.class, userId);
1484 Folder folder = dao.getEntityById(Folder.class, folderId);
1485 if(!folder.hasReadPermission(user))
1486 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1487 Set<Permission> perms = folder.getPermissions();
1488 Set<PermissionDTO> result = new LinkedHashSet<PermissionDTO>();
1489 for (Permission perm : perms)
1490 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId()))
1491 result.add(perm.getDTO());
1492 for (Permission perm : perms)
1493 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId())) {
1495 result.add(perm.getDTO());
1501 * Set the provided permissions as the new permissions of the specified
1506 * @param permissions
1507 * @throws ObjectNotFoundException
1508 * @throws InsufficientPermissionsException
1510 private void setFolderPermissions(User user, Folder folder, Set<PermissionDTO> permissions) throws ObjectNotFoundException, InsufficientPermissionsException {
1511 if (permissions != null && !permissions.isEmpty()) {
1512 User owner = folder.getOwner();
1513 PermissionDTO ownerPerm = null;
1514 for (PermissionDTO dto : permissions)
1515 if (dto.getUser() != null && dto.getUser().getId().equals(owner.getId())) {
1519 if (ownerPerm == null || !ownerPerm.hasRead() || !ownerPerm.hasWrite() || !ownerPerm.hasModifyACL())
1520 throw new InsufficientPermissionsException("Can't remove permissions from owner");
1521 // Delete previous entries
1522 for (Permission perm: folder.getPermissions())
1524 folder.getPermissions().clear();
1525 for (PermissionDTO dto : permissions) {
1526 // Skip 'empty' permission entries.
1527 if (!dto.getRead() && !dto.getWrite() && !dto.getModifyACL()) continue;
1528 folder.addPermission(getPermission(dto));
1531 for (FileHeader file : folder.getFiles()) {
1532 setFilePermissions(file, permissions);
1533 Date now = new Date();
1534 file.getAuditInfo().setModificationDate(now);
1535 file.getAuditInfo().setModifiedBy(user);
1537 for (Folder sub : folder.getSubfolders())
1538 setFolderPermissions(user, sub, permissions);
1542 private Permission getPermission(PermissionDTO dto) throws ObjectNotFoundException {
1543 Permission res = new Permission();
1544 if (dto.getGroup() != null)
1545 res.setGroup(dao.getEntityById(Group.class, dto.getGroup().getId()));
1546 else if (dto.getUser() != null)
1547 if (dto.getUser().getId() == null)
1548 res.setUser(dao.getUser(dto.getUser().getUsername()));
1550 res.setUser(dao.getEntityById(User.class, dto.getUser().getId()));
1551 res.setRead(dto.hasRead());
1552 res.setWrite(dto.hasWrite());
1553 res.setModifyACL(dto.hasModifyACL());
1558 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsersByUserNameLike(java.lang.String)
1561 public List<UserDTO> getUsersByUserNameLike(String username) {
1562 List<User> users = dao.getUsersByUserNameLike(username);
1563 List<UserDTO> result = new ArrayList<UserDTO>();
1564 for (User u : users)
1565 result.add(u.getDTO());
1571 public void addUserToGroup(Long userId, Long groupId, Long userToAddId) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
1573 throw new ObjectNotFoundException("No user specified");
1574 if (groupId == null)
1575 throw new ObjectNotFoundException("No group specified");
1576 if (userToAddId == null)
1577 throw new ObjectNotFoundException("No user to add specified");
1578 User user = dao.getEntityById(User.class, userId);
1579 Group group = dao.getEntityById(Group.class, groupId);
1580 if (!group.getOwner().equals(user))
1581 throw new InsufficientPermissionsException();
1582 User userToAdd = dao.getEntityById(User.class, userToAddId);
1583 if (group.contains(userToAdd))
1584 throw new DuplicateNameException("User already exists in group");
1585 group.getMembers().add(userToAdd);
1591 public void invalidateUserToken(Long userId) throws ObjectNotFoundException {
1593 throw new ObjectNotFoundException("No user specified");
1594 User user = dao.getEntityById(User.class, userId);
1595 user.invalidateAuthToken();
1600 public List<FolderDTO> getSharedRootFolders(Long userId) throws ObjectNotFoundException {
1602 throw new ObjectNotFoundException("No user specified");
1603 List<Folder> folders = dao.getSharedRootFolders(userId);
1604 List<FolderDTO> result = new ArrayList<FolderDTO>();
1605 for (Folder f : folders) {
1606 FolderDTO dto = f.getDTO();
1607 dto.setSubfolders(getSharedSubfolders(userId, f.getId()));
1614 public void removeMemberFromGroup(Long userId, Long groupId, Long memberId) throws ObjectNotFoundException, InsufficientPermissionsException {
1616 throw new ObjectNotFoundException("No user specified");
1617 if (groupId == null)
1618 throw new ObjectNotFoundException("No group specified");
1619 if (memberId == null)
1620 throw new ObjectNotFoundException("No member specified");
1621 User owner = dao.getEntityById(User.class, userId);
1622 Group group = dao.getEntityById(Group.class, groupId);
1623 User member = dao.getEntityById(User.class, memberId);
1624 if (!group.getOwner().equals(owner))
1625 throw new InsufficientPermissionsException("User is not the owner of the group");
1626 group.removeMemberFromGroup(member);
1632 public List<UserDTO> getUsersSharingFoldersForUser(Long userId) throws ObjectNotFoundException {
1633 List<User> users = dao.getUsersSharingFoldersForUser(userId);
1634 List<User> usersFiles = dao.getUsersSharingFilesForUser(userId);
1635 List<UserDTO> res = new ArrayList<UserDTO>();
1636 for (User u : users)
1637 res.add(u.getDTO());
1638 for(User fu : usersFiles)
1639 if(!users.contains(fu))
1640 res.add(fu.getDTO());
1645 public Set<PermissionDTO> getFilePermissions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1647 throw new ObjectNotFoundException("No user specified");
1649 throw new ObjectNotFoundException("No folder specified");
1650 User user = dao.getEntityById(User.class, userId);
1651 FileHeader folder = dao.getEntityById(FileHeader.class, fileId);
1652 if(!folder.hasReadPermission(user))
1653 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1654 Set<Permission> perms = folder.getPermissions();
1655 Set<PermissionDTO> result = new LinkedHashSet<PermissionDTO>();
1656 for (Permission perm : perms)
1657 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId()))
1658 result.add(perm.getDTO());
1659 for (Permission perm : perms)
1660 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId())) {
1662 result.add(perm.getDTO());
1667 * Set the provided permissions as the new permissions of the specified
1668 * file. This method sets the modification date/user attributes to the
1669 * current values as a side effect.
1672 * @param permissions
1673 * @throws ObjectNotFoundException
1674 * @throws InsufficientPermissionsException
1676 private void setFilePermissions(FileHeader file,
1677 Set<PermissionDTO> permissions)
1678 throws ObjectNotFoundException, InsufficientPermissionsException {
1679 if (permissions != null && !permissions.isEmpty()) {
1680 PermissionDTO ownerPerm = null;
1681 for (PermissionDTO dto : permissions)
1682 if (dto.getUser() != null && dto.getUser().getId().equals(file.getOwner().getId())) {
1686 if (ownerPerm == null || !ownerPerm.hasRead() || !ownerPerm.hasWrite() || !ownerPerm.hasModifyACL())
1687 throw new InsufficientPermissionsException("Can't remove permissions from owner");
1688 // Delete previous entries.
1689 for (Permission perm: file.getPermissions())
1691 file.getPermissions().clear();
1692 for (PermissionDTO dto : permissions) {
1693 // Skip 'empty' permission entries.
1694 if (!dto.getRead() && !dto.getWrite() && !dto.getModifyACL()) continue;
1695 file.addPermission(getPermission(dto));
1702 public List<FileHeaderDTO> getSharedFilesNotInSharedFolders(Long userId) throws ObjectNotFoundException {
1704 throw new ObjectNotFoundException("No user specified");
1705 List<FileHeader> files = dao.getSharedFilesNotInSharedFolders(userId);
1706 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1707 for (FileHeader f : files)
1708 result.add(f.getDTO());
1713 public List<FileHeaderDTO> getSharedFiles(Long userId) throws ObjectNotFoundException {
1715 throw new ObjectNotFoundException("No user specified");
1716 List<FileHeader> files = dao.getSharedFiles(userId);
1717 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1718 for (FileHeader f : files)
1719 result.add(f.getDTO());
1724 public List<FolderDTO> getSharedFolders(Long userId) throws ObjectNotFoundException {
1726 throw new ObjectNotFoundException("No user specified");
1727 List<Folder> folders = dao.getSharedFolders(userId);
1728 List<FolderDTO> result = new ArrayList<FolderDTO>();
1729 for (Folder f : folders)
1730 result.add(f.getDTO());
1735 public List<FileHeaderDTO> getSharedFiles(Long ownerId, Long callingUserId) throws ObjectNotFoundException {
1736 if (ownerId == null)
1737 throw new ObjectNotFoundException("No owner specified");
1738 if (callingUserId == null)
1739 throw new ObjectNotFoundException("No calling user specified");
1740 List<FileHeader> folders = dao.getSharedFiles(ownerId, callingUserId);
1741 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1742 for (FileHeader f : folders)
1743 result.add(f.getDTO());
1748 public List<FolderDTO> getSharedRootFolders(Long ownerId, Long callingUserId) throws ObjectNotFoundException {
1749 if (ownerId == null)
1750 throw new ObjectNotFoundException("No owner specified");
1751 if (callingUserId == null)
1752 throw new ObjectNotFoundException("No calling user specified");
1753 List<Folder> folders = dao.getSharedRootFolders(ownerId, callingUserId);
1754 List<FolderDTO> result = new ArrayList<FolderDTO>();
1755 for (Folder f : folders) {
1756 FolderDTO dto = f.getDTO();
1757 dto.setSubfolders(getSharedSubfolders(ownerId, callingUserId, f.getId()));
1765 public List<FolderDTO> getSharedSubfolders(Long userId, Long folderId) throws ObjectNotFoundException {
1767 throw new ObjectNotFoundException("No user specified");
1768 if (folderId == null)
1769 throw new ObjectNotFoundException("No folder specified");
1770 User user = dao.getEntityById(User.class, userId);
1771 Folder folder = dao.getEntityById(Folder.class, folderId);
1772 List<FolderDTO> result = new ArrayList<FolderDTO>();
1773 if (folder.isShared(user))
1774 for (Folder f : folder.getSubfolders())
1775 if (f.isShared(user) && !f.isDeleted())
1776 result.add(f.getDTO());
1781 public List<FolderDTO> getSharedSubfolders(Long userId, Long callingUserId, Long folderId) throws ObjectNotFoundException {
1783 throw new ObjectNotFoundException("No user specified");
1784 if (callingUserId == null)
1785 throw new ObjectNotFoundException("No user specified");
1786 if (folderId == null)
1787 throw new ObjectNotFoundException("No folder specified");
1788 User user = dao.getEntityById(User.class, callingUserId);
1789 Folder folder = dao.getEntityById(Folder.class, folderId);
1790 List<FolderDTO> result = new ArrayList<FolderDTO>();
1791 if (folder.isSharedForOtherUser(user))
1792 for (Folder f : folder.getSubfolders())
1793 if (f.isSharedForOtherUser(user) && !f.isDeleted()){
1794 FolderDTO dto = f.getDTO();
1795 dto.setSubfolders(getSharedSubfolders(userId, callingUserId, dto.getId()));
1803 public List<FileHeaderDTO> searchFiles(Long userId, String query) throws ObjectNotFoundException {
1805 throw new ObjectNotFoundException("No user specified");
1806 User user = getUser(userId);
1808 throw new ObjectNotFoundException("No query specified");
1809 List<FileHeader> files = search(user.getId(), query);
1810 List<FileHeaderDTO> res = new ArrayList<FileHeaderDTO>();
1811 for(FileHeader f : files)
1812 res.add(f.getDTO());
1817 * Performs the actuals search on the solr server and returns the results
1819 * We have to use the dismax query type (instead of the
1820 * standard) because it allows for search time field boosting. This is because we can't use indexing
1821 * time field boosting due to the patched rich indexing API that does not allow it
1825 * @return a List of FileHeader objects
1827 private List<FileHeader> search(Long userId, String query) {
1829 HttpClient httpClient = new HttpClient();
1831 GetMethod method = new GetMethod(getConfiguration().getString("solrSelectUrl"));
1832 NameValuePair[] params = {new NameValuePair("qt", "dismax"),
1833 new NameValuePair("q", query),
1834 new NameValuePair("sort", "score desc"),
1835 new NameValuePair("indent", "on")};
1836 method.setQueryString(params);
1839 String response = null;
1841 statusCode = httpClient.executeMethod(method);
1842 logger.debug("HTTP status: " + statusCode);
1843 response = method.getResponseBodyAsString();
1844 logger.debug(response);
1846 if (statusCode != 200 && retryCount < 3)
1848 Thread.sleep(3000); //Give Solr a little time to be available
1849 } catch (InterruptedException e) {
1851 } while (statusCode != 200 && retryCount < 3);
1852 if (statusCode != 200)
1853 throw new EJBException("Search query return error:\n" + response);
1855 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
1856 DocumentBuilder db = dbf.newDocumentBuilder();
1857 Document doc = db.parse(method.getResponseBodyAsStream());
1858 method.releaseConnection();
1860 Node root = doc.getElementsByTagName("response").item(0);
1861 Node lst = root.getFirstChild().getNextSibling();
1862 Node status = lst.getFirstChild().getNextSibling();
1863 if (status.getAttributes().getNamedItem("name").getNodeValue().equals("status") &&
1864 status.getTextContent().equals("0")) {
1865 List<FileHeader> fileResult = new ArrayList<FileHeader>();
1866 Node result = lst.getNextSibling().getNextSibling();
1867 NodeList docs = result.getChildNodes();
1868 User user = getUser(userId);
1869 for (int i=1; i<docs.getLength(); i=i+2) {
1870 Node d = docs.item(i);
1871 NodeList docData = d.getChildNodes();
1872 for (int j=1; j<docData.getLength(); j=j+2) {
1873 Node dd = docData.item(j);
1874 if (dd.getAttributes().item(0).getNodeName().equals("name") &&
1875 dd.getAttributes().item(0).getNodeValue().equals("id")) {
1876 Long fileId = Long.valueOf(dd.getTextContent());
1878 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1879 if (file.hasReadPermission(user)) {
1880 fileResult.add(file);
1881 logger.debug("File added " + fileId);
1883 } catch (ObjectNotFoundException e) {
1884 logger.warn("Search result not found", e);
1891 throw new EJBException();
1892 } catch (HttpException e) {
1893 throw new EJBException(e);
1894 } catch (IOException e) {
1895 throw new EJBException(e);
1896 } catch (SAXException e) {
1897 throw new EJBException(e);
1898 } catch (ParserConfigurationException e) {
1899 throw new EJBException(e);
1900 } catch (ObjectNotFoundException e) {
1901 throw new EJBException(e);
1906 public void copyFiles(Long userId, List<Long> fileIds, Long destId) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
1907 for(Long l : fileIds){
1908 FileHeader file = dao.getEntityById(FileHeader.class, l);
1909 copyFile(userId, l, destId, file.getName());
1916 public void moveFiles(Long userId, List<Long> fileIds, Long destId) throws InsufficientPermissionsException, ObjectNotFoundException, QuotaExceededException {
1917 for(Long l : fileIds){
1918 FileHeader file = dao.getEntityById(FileHeader.class, l);
1919 moveFile(userId, l, destId, file.getName());
1925 public void deleteFiles(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1927 throw new ObjectNotFoundException("No user specified");
1928 final User user = dao.getEntityById(User.class, userId);
1929 List<String> filesToRemove = new ArrayList<String>();
1930 //first delete database objects
1931 for(Long fileId : fileIds){
1933 throw new ObjectNotFoundException("No file specified");
1934 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1935 final Folder parent = file.getFolder();
1937 throw new ObjectNotFoundException("The specified file has no parent folder");
1938 if (!file.hasDeletePermission(user))
1939 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
1941 parent.removeFile(file);
1942 for (final FileBody body : file.getBodies())
1943 filesToRemove.add(body.getStoredFilePath());
1945 touchParentFolders(parent, user, new Date());
1947 //then remove physical files if everything is ok
1948 for(String physicalFileName : filesToRemove)
1949 deleteActualFile(physicalFileName);
1950 //then unindex deleted files
1951 for(Long fileId : fileIds)
1952 indexFile(fileId, true);
1957 public void moveFilesToTrash(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1958 for(Long l : fileIds)
1959 moveFileToTrash(userId, l);
1964 public void removeFilesFromTrash(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1965 for(Long l : fileIds)
1966 removeFileFromTrash(userId, l);
1971 public Nonce createNonce(Long userId) throws ObjectNotFoundException {
1973 throw new ObjectNotFoundException("No user specified");
1974 User user = dao.getEntityById(User.class, userId);
1975 Nonce nonce = Nonce.createNonce(user.getId());
1981 public Nonce getNonce(String nonce, Long userId) throws ObjectNotFoundException {
1983 throw new ObjectNotFoundException("No user specified");
1985 throw new ObjectNotFoundException("No nonce specified");
1986 return dao.getNonce(nonce, userId);
1990 public void removeNonce(Long id) throws ObjectNotFoundException {
1992 throw new ObjectNotFoundException("No nonce specified");
1993 Nonce nonce = dao.getEntityById(Nonce.class, id);
1998 public void activateUserNonce(Long userId, String nonce, Date nonceExpiryDate) throws ObjectNotFoundException {
2000 throw new ObjectNotFoundException("No user specified");
2001 User user = dao.getEntityById(User.class, userId);
2002 user.setNonce(nonce);
2003 user.setNonceExpiryDate(nonceExpiryDate);
2007 public StatsDTO getUserStatistics(Long userId) throws ObjectNotFoundException {
2009 throw new ObjectNotFoundException("No user specified");
2010 StatsDTO stats = new StatsDTO();
2011 stats.setFileCount(dao.getFileCount(userId));
2012 Long fileSize = dao.getFileSize(userId);
2013 stats.setFileSize(fileSize);
2014 Long quota = getQuota(userId);
2015 Long quotaLeft = quota - fileSize;
2016 stats.setQuotaLeftSize(quotaLeft);
2021 public List<FileBodyDTO> getVersions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
2023 throw new ObjectNotFoundException("No user specified");
2025 throw new ObjectNotFoundException("No file specified");
2026 User user = dao.getEntityById(User.class, userId);
2027 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
2028 if(!header.hasReadPermission(user))
2029 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2030 List<FileBodyDTO> result = new LinkedList<FileBodyDTO>();
2031 for(int i = header.getBodies().size()-1 ; i>=0; i--)
2032 result.add(header.getBodies().get(i).getDTO());
2037 public void removeVersion(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
2039 throw new ObjectNotFoundException("No user specified");
2041 throw new ObjectNotFoundException("No file specified");
2043 throw new ObjectNotFoundException("No body specified");
2044 User user = dao.getEntityById(User.class, userId);
2045 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
2046 if(!header.hasWritePermission(user))
2047 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2048 FileBody body = dao.getEntityById(FileBody.class, bodyId);
2049 if(body.equals(header.getCurrentBody())){
2051 if(header.getBodies().size() == 1)
2052 throw new InsufficientPermissionsException("You cant delete this version, Delete file instead!");
2053 for(FileBody b : header.getBodies())
2054 if(b.getVersion() == body.getVersion()-1)
2055 header.setCurrentBody(b);
2057 deleteActualFile(body.getStoredFilePath());
2058 header.getBodies().remove(body);
2060 Folder parent = header.getFolder();
2061 touchParentFolders(parent, user, new Date());
2066 public void restoreVersion(Long userId, Long fileId, int version) throws ObjectNotFoundException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
2068 throw new ObjectNotFoundException("No user specified");
2070 throw new ObjectNotFoundException("No file specified");
2071 User user = dao.getEntityById(User.class, userId);
2072 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
2073 if(!header.hasWritePermission(user))
2074 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2075 FileBody body = dao.getFileVersion(fileId, version);
2076 final File fileContents = new File(body.getStoredFilePath());
2079 updateFileContents(userId, fileId, body.getMimeType(), new FileInputStream(fileContents) );
2080 } catch (FileNotFoundException e) {
2081 throw new GSSIOException(e);
2087 * @see gr.ebs.gss.server.ejb.ExternalAPI#removeOldVersions(java.lang.Long, java.lang.Long)
2090 public void removeOldVersions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
2092 throw new ObjectNotFoundException("No user specified");
2094 throw new ObjectNotFoundException("No file specified");
2095 User user = dao.getEntityById(User.class, userId);
2096 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
2097 if(!header.hasWritePermission(user))
2098 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2099 Iterator<FileBody> it = header.getBodies().iterator();
2100 while(it.hasNext()){
2101 FileBody body = it.next();
2102 if(!body.equals(header.getCurrentBody())){
2103 deleteActualFile(body.getStoredFilePath());
2108 header.getCurrentBody().setVersion(1);
2110 Folder parent = header.getFolder();
2111 touchParentFolders(parent, user, new Date());
2115 * Gets the quota left for specified user ID.
2117 private Long getQuotaLeft(Long userId) throws ObjectNotFoundException{
2118 Long fileSize = dao.getFileSize(userId);
2119 Long quota = getQuota(userId);
2120 return quota - fileSize;
2124 * Gets the quota for specified user ID.
2126 private Long getQuota(Long userId) throws ObjectNotFoundException{
2127 UserClass uc = getUser(userId).getUserClass();
2129 uc = getDefaultUserClass();
2130 return uc.getQuota();
2134 public void rebuildSolrIndex() {
2135 MessageProducer sender = null;
2136 Session session = null;
2137 Connection qConn = null;
2139 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
2140 DocumentBuilder db = dbf.newDocumentBuilder();
2141 Document doc = db.newDocument();
2142 Node root = doc.createElement("delete");
2143 doc.appendChild(root);
2144 Node queryNode = doc.createElement("query");
2145 root.appendChild(queryNode);
2146 queryNode.appendChild(doc.createTextNode("*:*"));
2148 TransformerFactory fact = TransformerFactory.newInstance();
2149 Transformer trans = fact.newTransformer();
2150 trans.setOutputProperty(OutputKeys.INDENT, "yes");
2151 StringWriter sw = new StringWriter();
2152 StreamResult sr = new StreamResult(sw);
2153 DOMSource source = new DOMSource(doc);
2154 trans.transform(source, sr);
2155 logger.debug(sw.toString());
2157 HttpClient httpClient = new HttpClient();
2158 PostMethod method = new PostMethod(getConfiguration().getString("solrUpdateUrl"));
2159 method.setRequestEntity(new StringRequestEntity(sw.toString()));
2162 String response = null;
2164 statusCode = httpClient.executeMethod(method);
2165 logger.debug("HTTP status: " + statusCode);
2166 response = method.getResponseBodyAsString();
2167 logger.debug(response);
2169 if (statusCode != 200 && retryCount < 3)
2171 Thread.sleep(10000); //Give Solr a little time to be available
2172 } catch (InterruptedException e) {
2174 } while (statusCode != 200 && retryCount < 3);
2175 method.releaseConnection();
2176 if (statusCode != 200)
2177 throw new EJBException("Cannot clear Solr index. Solr response is:\n" + response);
2178 List<Long> fileIds = dao.getAllFileIds();
2180 Context jndiCtx = new InitialContext();
2181 ConnectionFactory factory = (QueueConnectionFactory) jndiCtx.lookup("java:/JmsXA");
2182 Queue queue = (Queue) jndiCtx.lookup("queue/gss-indexingQueue");
2183 qConn = factory.createConnection();
2184 session = qConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
2185 sender = session.createProducer(queue);
2187 for (Long id : fileIds) {
2188 MapMessage map = session.createMapMessage();
2189 map.setObject("id", id);
2190 map.setBoolean("delete", false);
2193 sendOptimize(httpClient, 0);
2194 } catch (DOMException e) {
2195 throw new EJBException(e);
2196 } catch (TransformerConfigurationException e) {
2197 throw new EJBException(e);
2198 } catch (IllegalArgumentException e) {
2199 throw new EJBException(e);
2200 } catch (HttpException e) {
2201 throw new EJBException(e);
2202 } catch (UnsupportedEncodingException e) {
2203 throw new EJBException(e);
2204 } catch (ParserConfigurationException e) {
2205 throw new EJBException(e);
2206 } catch (TransformerException e) {
2207 throw new EJBException(e);
2208 } catch (IOException e) {
2209 throw new EJBException(e);
2210 } catch (NamingException e) {
2211 throw new EJBException(e);
2212 } catch (JMSException e) {
2213 throw new EJBException(e);
2219 if (session != null)
2224 catch (JMSException e) {
2231 * Sends a optimize message to the solr server
2234 * @param retryCount If the commit fails, it is retried three times. This parameter is passed in the recursive
2235 * calls to stop the recursion
2236 * @throws UnsupportedEncodingException
2237 * @throws IOException
2238 * @throws HttpException
2240 private void sendOptimize(HttpClient httpClient, int retryCount) throws UnsupportedEncodingException, IOException, HttpException {
2241 PostMethod method = null;
2243 logger.debug("Optimize retry: " + retryCount);
2244 method = new PostMethod(getConfiguration().getString("solrUpdateUrl"));
2245 method.setRequestEntity(new StringRequestEntity("<optimize/>", "text/xml", "iso8859-1"));
2246 int statusCode = httpClient.executeMethod(method);
2247 logger.debug("HTTP status: " + statusCode);
2248 String response = method.getResponseBodyAsString();
2249 logger.debug(response);
2250 if (statusCode != 200 && retryCount < 2) {
2252 Thread.sleep(10000); //Give Solr a little time to be available
2253 } catch (InterruptedException e) {
2255 sendOptimize(httpClient, retryCount + 1);
2260 method.releaseConnection();
2265 public FileHeaderDTO createFile(Long userId, Long folderId, String name, String mimeType, long fileSize, String filePath)
2266 throws DuplicateNameException, ObjectNotFoundException, GSSIOException,
2267 InsufficientPermissionsException, QuotaExceededException {
2270 throw new ObjectNotFoundException("No user specified");
2271 if (folderId == null)
2272 throw new ObjectNotFoundException("No folder specified");
2273 String contentType = mimeType;
2274 if (StringUtils.isEmpty(mimeType))
2275 contentType = DEFAULT_MIME_TYPE;
2276 if (StringUtils.isEmpty(name))
2277 throw new ObjectNotFoundException("No file name specified");
2278 if (dao.existsFolderOrFile(folderId, name))
2279 throw new DuplicateNameException("A folder or file with the name '" + name +
2280 "' already exists at this level");
2282 // Do the actual work.
2283 Folder parent = null;
2285 parent = dao.getEntityById(Folder.class, folderId);
2286 } catch (final ObjectNotFoundException onfe) {
2287 // Supply a more accurate problem description.
2288 throw new ObjectNotFoundException("Parent folder not found");
2290 final User owner = dao.getEntityById(User.class, userId);
2291 if (!parent.hasWritePermission(owner))
2292 throw new InsufficientPermissionsException("You don't have the permissions to write to this folder");
2293 final FileHeader file = new FileHeader();
2295 parent.addFile(file);
2296 // set file owner to folder owner
2297 file.setOwner(parent.getOwner());
2298 //set file's readForAll value according to parent folder readForAll value
2299 file.setReadForAll(parent.isReadForAll());
2301 final Date now = new Date();
2302 final AuditInfo auditInfo = new AuditInfo();
2303 auditInfo.setCreatedBy(owner);
2304 auditInfo.setCreationDate(now);
2305 auditInfo.setModifiedBy(owner);
2306 auditInfo.setModificationDate(now);
2307 file.setAuditInfo(auditInfo);
2308 // TODO set the proper versioning flag on creation
2309 file.setVersioned(false);
2311 for (final Permission p : parent.getPermissions()) {
2312 final Permission permission = new Permission();
2313 permission.setGroup(p.getGroup());
2314 permission.setUser(p.getUser());
2315 permission.setRead(p.getRead());
2316 permission.setWrite(p.getWrite());
2317 permission.setModifyACL(p.getModifyACL());
2318 file.addPermission(permission);
2321 // Create the file body.
2323 createFileBody(name, contentType, fileSize, filePath, file, auditInfo);
2324 } catch (FileNotFoundException e) {
2325 throw new GSSIOException(e);
2327 touchParentFolders(parent, owner, new Date());
2329 indexFile(file.getId(), false);
2331 return file.getDTO();
2335 public FileHeaderDTO updateFileContents(Long userId, Long fileId, String mimeType, long fileSize, String filePath) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
2337 throw new ObjectNotFoundException("No user specified");
2339 throw new ObjectNotFoundException("No file specified");
2340 String contentType = mimeType;
2342 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
2344 // if no mime type or the generic mime type is defined by the client, then try to identify it from the filename extension
2345 if (StringUtils.isEmpty(mimeType) || "application/octet-stream".equals(mimeType)
2346 || "application/download".equals(mimeType) || "application/force-download".equals(mimeType)
2347 || "octet/stream".equals(mimeType) || "application/unknown".equals(mimeType))
2348 contentType = identifyMimeType(file.getName());
2350 final User owner = dao.getEntityById(User.class, userId);
2351 if (!file.hasWritePermission(owner))
2352 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2353 final Date now = new Date();
2354 final AuditInfo auditInfo = new AuditInfo();
2355 auditInfo.setCreatedBy(owner);
2356 auditInfo.setCreationDate(now);
2357 auditInfo.setModifiedBy(owner);
2358 auditInfo.setModificationDate(now);
2360 createFileBody(file.getName(), contentType, fileSize, filePath, file, auditInfo);
2361 } catch (FileNotFoundException e) {
2362 throw new GSSIOException(e);
2364 Folder parent = file.getFolder();
2365 touchParentFolders(parent, owner, new Date());
2367 indexFile(fileId, false);
2368 return file.getDTO();
2372 * Helper method for identifying mime type by examining the filename extension
2375 * @return the mime type
2377 private String identifyMimeType(String filename) {
2378 if (filename.indexOf('.') != -1) {
2379 String extension = filename.substring(filename.lastIndexOf('.')).toLowerCase(Locale.ENGLISH);
2380 if (".doc".equals(extension))
2381 return "application/msword";
2382 else if (".xls".equals(extension))
2383 return "application/vnd.ms-excel";
2384 else if (".ppt".equals(extension))
2385 return "application/vnd.ms-powerpoint";
2386 else if (".pdf".equals(extension))
2387 return "application/pdf";
2388 else if (".gif".equals(extension))
2390 else if (".jpg".equals(extension) || ".jpeg".equals(extension) || ".jpe".equals(extension))
2391 return "image/jpeg";
2392 else if (".tiff".equals(extension) || ".tif".equals(extension))
2393 return "image/tiff";
2394 else if (".png".equals(extension))
2396 else if (".bmp".equals(extension))
2399 // when all else fails assign the default mime type
2400 return DEFAULT_MIME_TYPE;
2404 * Helper method to create a new file body and attach it as the current body
2405 * of the provided file header.
2407 * @param name the original file name
2408 * @param mimeType the content type
2409 * @param fileSize the uploaded file size
2410 * @param filePath the uploaded file full path
2411 * @param header the file header that will be associated with the new body
2412 * @param auditInfo the audit info
2413 * @param owner the owner of the file
2414 * @throws FileNotFoundException
2415 * @throws QuotaExceededException
2416 * @throws ObjectNotFoundException if the owner was not found
2418 private void createFileBody(String name, String mimeType, long fileSize, String filePath,
2419 FileHeader header, AuditInfo auditInfo)
2420 throws FileNotFoundException, QuotaExceededException, ObjectNotFoundException {
2422 long currentTotalSize = 0;
2423 if (!header.isVersioned() && header.getCurrentBody() != null && header.getBodies() != null)
2424 currentTotalSize = header.getTotalSize();
2425 Long quotaLeft = getQuotaLeft(header.getOwner().getId());
2426 if(quotaLeft < fileSize-currentTotalSize) {
2427 // quota exceeded -> delete the file
2428 deleteActualFile(filePath);
2429 throw new QuotaExceededException("Not enough free space available");
2432 FileBody body = new FileBody();
2434 // if no mime type or the generic mime type is defined by the client, then try to identify it from the filename extension
2435 if (StringUtils.isEmpty(mimeType) || "application/octet-stream".equals(mimeType)
2436 || "application/download".equals(mimeType) || "application/force-download".equals(mimeType)
2437 || "octet/stream".equals(mimeType) || "application/unknown".equals(mimeType))
2438 body.setMimeType(identifyMimeType(name));
2440 body.setMimeType(mimeType);
2441 body.setAuditInfo(auditInfo);
2442 body.setFileSize(fileSize);
2443 body.setOriginalFilename(name);
2444 body.setStoredFilePath(filePath);
2445 //CLEAR OLD VERSION IF FILE IS NOT VERSIONED AND GETS UPDATED
2446 if(!header.isVersioned() && header.getCurrentBody() != null){
2447 header.setCurrentBody(null);
2448 if (header.getBodies() != null) {
2449 Iterator<FileBody> it = header.getBodies().iterator();
2450 while(it.hasNext()){
2451 FileBody bo = it.next();
2452 deleteActualFile(bo.getStoredFilePath());
2460 header.addBody(body);
2461 header.setAuditInfo(auditInfo);
2468 @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
2469 public File uploadFile(InputStream stream, Long userId) throws IOException, ObjectNotFoundException {
2471 throw new ObjectNotFoundException("No user specified");
2472 User owner = dao.getEntityById(User.class, userId);
2474 throw new ObjectNotFoundException("No user specified");
2475 long start = 0, end = 0;
2476 if (logger.isDebugEnabled())
2477 start = System.currentTimeMillis();
2478 File result = new File(generateRepositoryFilePath());
2480 final FileOutputStream output = new FileOutputStream(result);
2481 final byte[] buffer = new byte[UPLOAD_BUFFER_SIZE];
2484 while (-1 != (n = stream.read(buffer)))
2485 output.write(buffer, 0, n);
2488 } catch (IOException e) {
2489 if (!result.delete())
2490 logger.warn("Could not delete " + result.getPath());
2493 if (logger.isDebugEnabled()) {
2494 end = System.currentTimeMillis();
2495 logger.debug("Time to upload: " + (end - start) + " (msec)");
2502 public void createFileUploadProgress(Long userId, String filename, Long bytesTransfered, Long fileSize) throws ObjectNotFoundException{
2505 throw new ObjectNotFoundException("No user specified");
2506 User user = dao.getEntityById(User.class, userId);
2507 FileUploadStatus status = dao.getFileUploadStatus(userId, filename);
2509 status = new FileUploadStatus();
2510 status.setOwner(user);
2511 status.setFilename(filename);
2512 status.setBytesUploaded(bytesTransfered);
2513 status.setFileSize(fileSize);
2517 status.setBytesUploaded(bytesTransfered);
2518 status.setFileSize(fileSize);
2525 public void removeFileUploadProgress(Long userId, String filename) throws ObjectNotFoundException{
2527 throw new ObjectNotFoundException("No user specified");
2528 FileUploadStatus status = dao.getFileUploadStatus(userId, filename);
2534 public FileUploadStatus getFileUploadStatus(Long userId, String fileName) {
2535 return dao.getFileUploadStatus(userId, fileName);
2539 public FolderDTO getFolderWithSubfolders(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
2541 throw new ObjectNotFoundException("No user specified");
2542 if (folderId == null)
2543 throw new ObjectNotFoundException("No folder specified");
2544 final User user = dao.getEntityById(User.class, userId);
2545 final Folder folder = dao.getEntityById(Folder.class, folderId);
2546 // Check permissions
2547 if (!folder.hasReadPermission(user))
2548 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
2549 List<FolderDTO> subfolders = new ArrayList<FolderDTO>();
2550 if (folder.hasReadPermission(user))
2551 for (Folder f : folder.getSubfolders())
2552 if (f.hasReadPermission(user) && !f.isDeleted())
2553 subfolders.add(f.getDTO());
2554 FolderDTO result = folder.getDTO();
2555 result.setSubfolders(subfolders);
2556 return folder.getDTO();
2560 public FolderDTO getFolderWithSubfolders(Long userId, Long callingUserId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
2562 throw new ObjectNotFoundException("No user specified");
2563 if (folderId == null)
2564 throw new ObjectNotFoundException("No folder specified");
2565 User user = dao.getEntityById(User.class, callingUserId);
2566 Folder folder = dao.getEntityById(Folder.class, folderId);
2567 // Check permissions
2568 if (!folder.hasReadPermission(user))
2569 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
2571 FolderDTO result = folder.getDTO();
2572 result.setSubfolders(getSharedSubfolders(userId, callingUserId, folder.getId()));
2577 public FileBodyDTO getFileVersion(Long userId, Long fileId, int version)
2578 throws ObjectNotFoundException, InsufficientPermissionsException {
2580 throw new ObjectNotFoundException("No user specified");
2582 throw new ObjectNotFoundException("No file specified");
2584 throw new ObjectNotFoundException("No valid version specified");
2585 User user = dao.getEntityById(User.class, userId);
2586 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
2587 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
2588 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2589 FileBody body = dao.getFileVersion(fileId, version);
2590 return body.getDTO();
2594 public User updateUserPolicyAcceptance(Long userId, boolean isAccepted) throws ObjectNotFoundException {
2596 throw new ObjectNotFoundException("No user specified");
2597 User user = dao.getEntityById(User.class, userId);
2598 user.setAcceptedPolicy(isAccepted);
2603 public void updateAccounting(User user, Date date, long bandwidthDiff) {
2604 dao.updateAccounting(user, date, bandwidthDiff);
2608 public boolean canReadFolder(Long userId, Long folderId) throws ObjectNotFoundException {
2610 throw new ObjectNotFoundException("No user specified");
2611 if (folderId == null)
2612 throw new ObjectNotFoundException("No folder specified");
2613 User user = dao.getEntityById(User.class, userId);
2614 Folder folder = dao.getEntityById(Folder.class, folderId);
2615 // Check permissions
2616 if (!folder.hasReadPermission(user))
2622 public String resetWebDAVPassword(Long userId) throws ObjectNotFoundException {
2624 throw new ObjectNotFoundException("No user specified");
2625 User user = dao.getEntityById(User.class, userId);
2626 user.generateWebDAVPassword();
2627 return user.getWebDAVPassword();
2631 public Invitation findInvite(String code) {
2634 return dao.findInvite(code);
2638 public void createLdapUser(String username, String firstname, String lastname, String email, String password) {
2639 LDAPConnection lc = new LDAPConnection();
2640 LDAPAttributeSet attributeSet = new LDAPAttributeSet();
2641 attributeSet.add(new LDAPAttribute("objectClass", getConfiguration().getStringArray("objectClass")));
2642 attributeSet.add(new LDAPAttribute("uid", username));
2643 attributeSet.add(new LDAPAttribute("cn", new String[]{firstname + " " + lastname}));
2644 attributeSet.add(new LDAPAttribute("sn", lastname));
2645 attributeSet.add(new LDAPAttribute("givenName", firstname));
2646 attributeSet.add(new LDAPAttribute("mail", email));
2647 attributeSet.add(new LDAPAttribute("userPassword", password));
2648 String dn = "uid=" + username + "," + getConfiguration().getString("baseDn");
2649 LDAPEntry newEntry = new LDAPEntry(dn, attributeSet);
2651 lc.connect(getConfiguration().getString("ldapHost"), LDAPConnection.DEFAULT_PORT);
2652 lc.bind(LDAPConnection.LDAP_V3, getConfiguration().getString("bindDn"),
2653 getConfiguration().getString("bindPassword").getBytes("UTF8"));
2655 logger.info("Successfully added LDAP account: " + dn);
2657 } catch(LDAPException e) {
2658 throw new RuntimeException(e);
2659 } catch(UnsupportedEncodingException e) {
2660 throw new RuntimeException(e);
2666 public UserClass upgradeUserClass(String username, String code) throws ObjectNotFoundException, InvitationUsedException {
2667 User user = findUser(username);
2669 throw new ObjectNotFoundException("The user was not found");
2670 Invitation invite = findInvite(code);
2671 if (invite.getUser() != null)
2672 throw new InvitationUsedException("This code has already been used");
2673 invite.setUser(user);
2674 UserClass couponClass = getCouponUserClass();
2675 user.setUserClass(couponClass);
2680 public UserClass getCouponUserClass() {
2681 return dao.findCouponUserClass();
2685 * Mark the folder as modified from the specified user and change it's modification date.
2687 private void touchFolder(Folder f, User owner, Date now){
2688 final AuditInfo auditInfo = new AuditInfo();
2689 auditInfo.setCreatedBy(owner);
2690 auditInfo.setCreationDate(now);
2691 auditInfo.setModifiedBy(owner);
2692 auditInfo.setModificationDate(now);
2693 f.setAuditInfo(auditInfo);
2697 * Mark the file as modified from the specified user and change it's modification date.
2699 private void touchFile(FileHeader f, User owner, Date now){
2700 final AuditInfo auditInfo = new AuditInfo();
2701 auditInfo.setCreatedBy(owner);
2702 auditInfo.setCreationDate(now);
2703 auditInfo.setModifiedBy(owner);
2704 auditInfo.setModificationDate(now);
2705 f.setAuditInfo(auditInfo);
2709 * Set the provided readForAll as the new readforAll value of the specified
2710 * folder and sub-folders.
2715 * @throws ObjectNotFoundException
2718 private void setFolderReadForAll(User user, Folder folder, Boolean readForAll){
2719 if (readForAll != null && user.equals(folder.getOwner())){
2720 folder.setReadForAll(readForAll);
2722 for (FileHeader file : folder.getFiles())
2723 file.setReadForAll(readForAll);
2725 //only update subfolders when readforall is true. otherwise all sub-folders stay untouched
2726 for (Folder sub : folder.getSubfolders())
2727 setFolderReadForAll(user, sub, readForAll);