2 * Copyright 2007, 2008, 2009, 2010 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.UserLogin;
41 import gr.ebs.gss.server.domain.dto.FileBodyDTO;
42 import gr.ebs.gss.server.domain.dto.FileHeaderDTO;
43 import gr.ebs.gss.server.domain.dto.FolderDTO;
44 import gr.ebs.gss.server.domain.dto.GroupDTO;
45 import gr.ebs.gss.server.domain.dto.PermissionDTO;
46 import gr.ebs.gss.server.domain.dto.StatsDTO;
47 import gr.ebs.gss.server.domain.dto.UserDTO;
50 import java.io.FileInputStream;
51 import java.io.FileNotFoundException;
52 import java.io.FileOutputStream;
53 import java.io.IOException;
54 import java.io.InputStream;
55 import java.io.StringWriter;
56 import java.io.UnsupportedEncodingException;
57 import java.util.ArrayList;
58 import java.util.Date;
59 import java.util.Iterator;
60 import java.util.LinkedHashSet;
61 import java.util.LinkedList;
62 import java.util.List;
63 import java.util.Locale;
64 import java.util.Random;
66 import java.util.StringTokenizer;
69 import javax.ejb.EJBException;
70 import javax.ejb.EJBTransactionRolledbackException;
71 import javax.ejb.Stateless;
72 import javax.ejb.TransactionAttribute;
73 import javax.ejb.TransactionAttributeType;
74 import javax.jms.Connection;
75 import javax.jms.ConnectionFactory;
76 import javax.jms.JMSException;
77 import javax.jms.MapMessage;
78 import javax.jms.MessageProducer;
79 import javax.jms.Queue;
80 import javax.jms.QueueConnectionFactory;
81 import javax.jms.Session;
82 import javax.naming.Context;
83 import javax.naming.InitialContext;
84 import javax.naming.NamingException;
85 import javax.persistence.PersistenceException;
86 import javax.xml.parsers.DocumentBuilder;
87 import javax.xml.parsers.DocumentBuilderFactory;
88 import javax.xml.parsers.ParserConfigurationException;
89 import javax.xml.transform.OutputKeys;
90 import javax.xml.transform.Transformer;
91 import javax.xml.transform.TransformerConfigurationException;
92 import javax.xml.transform.TransformerException;
93 import javax.xml.transform.TransformerFactory;
94 import javax.xml.transform.dom.DOMSource;
95 import javax.xml.transform.stream.StreamResult;
97 import org.apache.commons.httpclient.HttpClient;
98 import org.apache.commons.httpclient.HttpException;
99 import org.apache.commons.httpclient.NameValuePair;
100 import org.apache.commons.httpclient.methods.GetMethod;
101 import org.apache.commons.httpclient.methods.PostMethod;
102 import org.apache.commons.httpclient.methods.StringRequestEntity;
103 import org.apache.commons.lang.StringUtils;
104 import org.apache.commons.logging.Log;
105 import org.apache.commons.logging.LogFactory;
106 import org.hibernate.exception.ConstraintViolationException;
107 import org.w3c.dom.DOMException;
108 import org.w3c.dom.Document;
109 import org.w3c.dom.Node;
110 import org.w3c.dom.NodeList;
111 import org.xml.sax.SAXException;
113 import com.novell.ldap.LDAPAttribute;
114 import com.novell.ldap.LDAPAttributeSet;
115 import com.novell.ldap.LDAPConnection;
116 import com.novell.ldap.LDAPEntry;
117 import com.novell.ldap.LDAPException;
120 * The concrete implementation of the ExternalAPI interface.
125 public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
127 * The default MIME type for files without an explicit one.
129 private static final String DEFAULT_MIME_TYPE = "application/octet-stream";
132 * The size of the buffer that is used to temporarily store chunks of
133 * uploaded files, while storing them to the file repository.
135 private static final int UPLOAD_BUFFER_SIZE = 1024 * 4;
140 private static Log logger = LogFactory.getLog(ExternalAPIBean.class);
143 * Injected reference to the GSSDAO data access facade.
150 * A cached random number generator for creating unique filenames.
152 private static Random random = new Random();
155 * Mark the folder and all of its parent folders as modified from the specified user.
157 private void touchParentFolders(Folder folder, User user, Date date) {
160 AuditInfo ai = f.getAuditInfo();
161 ai.setModifiedBy(user);
162 ai.setModificationDate(date);
169 public FolderDTO getRootFolder(Long userId) throws ObjectNotFoundException {
171 throw new ObjectNotFoundException("No user specified");
172 Folder folder = dao.getRootFolder(userId);
173 return folder.getDTO();
177 public FolderDTO getFolder(final Long userId, final Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
179 throw new ObjectNotFoundException("No user specified");
180 if (folderId == null)
181 throw new ObjectNotFoundException("No folder specified");
182 final User user = dao.getEntityById(User.class, userId);
183 final Folder folder = dao.getEntityById(Folder.class, folderId);
185 if (!folder.hasReadPermission(user))
186 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
187 return folder.getDTO();
191 public User getUser(Long userId) throws ObjectNotFoundException {
193 throw new ObjectNotFoundException("No user specified");
194 return dao.getEntityById(User.class, userId);
198 public UserDTO getUserDTO(final Long userId) throws ObjectNotFoundException {
199 return getUser(userId).getDTO();
203 public GroupDTO getGroup(final Long groupId) throws ObjectNotFoundException {
205 throw new ObjectNotFoundException("No group specified");
206 final Group group = dao.getEntityById(Group.class, groupId);
207 return group.getDTO();
211 public GroupDTO getGroup(Long userId, String name) throws ObjectNotFoundException {
213 throw new ObjectNotFoundException("No user specified");
215 throw new ObjectNotFoundException("No group specified");
216 User user = dao.getEntityById(User.class, userId);
217 List<Group> groups = user.getGroupsSpecified();
218 for (Group group: groups)
219 if (group.getName().equals(name))
220 return group.getDTO();
221 throw new ObjectNotFoundException("Group " + name + " not found");
225 public List<GroupDTO> getGroups(final Long userId) throws ObjectNotFoundException {
227 throw new ObjectNotFoundException("No user specified");
228 final List<Group> groups = dao.getGroups(userId);
229 final List<GroupDTO> result = new ArrayList<GroupDTO>();
230 for (final Group g : groups)
231 result.add(g.getDTO());
236 public List<FileHeaderDTO> getFiles(Long userId, Long folderId, boolean ignoreDeleted)
237 throws ObjectNotFoundException, InsufficientPermissionsException {
240 throw new ObjectNotFoundException("No user specified");
241 if (folderId == null)
242 throw new ObjectNotFoundException("No folder specified");
243 User user = dao.getEntityById(User.class, userId);
244 Folder folder = dao.getEntityById(Folder.class, folderId);
245 if (!folder.hasReadPermission(user))
246 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
247 // Do the actual work.
248 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
249 List<FileHeader> files = dao.getFiles(folderId, userId, ignoreDeleted);
250 for (FileHeader f : files)
251 result.add(f.getDTO());
256 public List<UserDTO> getUsers(final Long userId, final Long groupId) throws ObjectNotFoundException {
259 throw new ObjectNotFoundException("No user specified");
261 throw new ObjectNotFoundException("No group specified");
263 // Do the actual work.
264 final List<User> users = dao.getUsers(groupId);
265 final List<UserDTO> result = new ArrayList<UserDTO>();
266 for (final User u : users)
267 result.add(u.getDTO());
272 public FolderDTO createFolder(Long userId, Long parentId, String name)
273 throws DuplicateNameException, ObjectNotFoundException, InsufficientPermissionsException {
276 throw new ObjectNotFoundException("No user specified");
277 if (StringUtils.isEmpty(name))
278 throw new ObjectNotFoundException("New folder name is empty");
279 if (parentId == null)
280 throw new ObjectNotFoundException("No parent specified");
281 if (dao.existsFolderOrFile(parentId, name))
282 throw new DuplicateNameException("A folder or file with the name '" +
283 name + "' already exists at this level");
285 User creator = dao.getEntityById(User.class, userId);
287 Folder parent = null;
289 parent = dao.getEntityById(Folder.class, parentId);
290 } catch (ObjectNotFoundException onfe) {
291 // Supply a more accurate problem description.
292 throw new ObjectNotFoundException("Parent folder not found");
294 if (!parent.hasWritePermission(creator))
295 throw new InsufficientPermissionsException("You don't have the permissions" +
296 " to write to this folder");
298 // Do the actual work.
299 return createFolder(name, parent, creator);
303 * Create a new folder with the provided name, parent and owner.
308 * @return the new folder
310 private FolderDTO createFolder(String name, Folder parent, User creator) {
311 Folder folder = new Folder();
312 folder.setName(name);
313 if (parent != null) {
314 parent.addSubfolder(folder);
315 folder.setOwner(parent.getOwner());
317 folder.setOwner(creator);
319 Date now = new Date();
320 AuditInfo auditInfo = new AuditInfo();
321 auditInfo.setCreatedBy(creator);
322 auditInfo.setCreationDate(now);
323 auditInfo.setModifiedBy(creator);
324 auditInfo.setModificationDate(now);
325 folder.setAuditInfo(auditInfo);
326 touchParentFolders(folder, auditInfo.getModifiedBy(), auditInfo.getModificationDate());
329 for (Permission p : parent.getPermissions()) {
330 Permission permission = new Permission();
331 permission.setGroup(p.getGroup());
332 permission.setUser(p.getUser());
333 permission.setRead(p.getRead());
334 permission.setWrite(p.getWrite());
335 permission.setModifyACL(p.getModifyACL());
336 folder.addPermission(permission);
339 Permission permission = new Permission();
340 permission.setUser(creator);
341 permission.setRead(true);
342 permission.setWrite(true);
343 permission.setModifyACL(true);
344 folder.addPermission(permission);
348 folder.setReadForAll(parent.isReadForAll());
351 return folder.getDTO();
355 public void deleteFolder(final Long userId, final Long folderId) throws InsufficientPermissionsException, ObjectNotFoundException {
358 throw new ObjectNotFoundException("No user specified");
359 if (folderId == null)
360 throw new ObjectNotFoundException("No folder specified");
362 // Do the actual work.
363 final Folder folder = dao.getEntityById(Folder.class, folderId);
364 final Folder parent = folder.getParent();
366 throw new ObjectNotFoundException("Deleting the root folder is not allowed");
367 final User user = dao.getEntityById(User.class, userId);
368 if (!folder.hasDeletePermission(user)) {
369 logger.info("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
370 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
372 removeSubfolderFiles(folder);
373 parent.removeSubfolder(folder);
375 touchParentFolders(parent, user, new Date());
379 * Traverses the folder and deletes all actual files (file system)
380 * regardless of permissions
384 private void removeSubfolderFiles(Folder folder) {
385 //remove files for all subfolders
386 for (Folder subfolder:folder.getSubfolders())
387 removeSubfolderFiles(subfolder);
388 //remove this folder's file bodies (actual files)
389 for (FileHeader file:folder.getFiles()) {
390 for (FileBody body:file.getBodies())
391 deleteActualFile(body.getStoredFilePath());
392 indexFile(file.getId(), true);
397 @SuppressWarnings("unchecked")
398 public List<FolderDTO> getSubfolders(Long userId, Long folderId)
399 throws ObjectNotFoundException, InsufficientPermissionsException {
401 throw new ObjectNotFoundException("No user specified");
402 if (folderId == null)
403 throw new ObjectNotFoundException("No folder specified");
404 User user = dao.getEntityById(User.class, userId);
405 Folder folder = dao.getEntityById(Folder.class, folderId);
406 if (!folder.hasReadPermission(user))
407 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
408 List<FolderDTO> result = new ArrayList<FolderDTO>();
409 if (folder.hasReadPermission(user))
410 for (Folder f : folder.getSubfolders())
411 if (f.hasReadPermission(user) && !f.isDeleted())
412 result.add(f.getDTO());
417 public FolderDTO updateFolder(Long userId, Long folderId, String folderName,
419 Set<PermissionDTO> permissions)
420 throws InsufficientPermissionsException, ObjectNotFoundException,
421 DuplicateNameException {
425 throw new ObjectNotFoundException("No user specified");
426 if (folderId == null)
427 throw new ObjectNotFoundException("No folder specified");
429 Folder folder = dao.getEntityById(Folder.class, folderId);
430 User user = dao.getEntityById(User.class, userId);
431 if (folderName != null && !folder.hasWritePermission(user))
432 throw new InsufficientPermissionsException("You don't have the necessary permissions");
433 if(permissions != null && !permissions.isEmpty() && !folder.hasModifyACLPermission(user))
434 throw new InsufficientPermissionsException("You don't have the necessary permissions");
435 // Check permissions for making file public.
436 if (readForAll != null && !user.equals(folder.getOwner()))
437 throw new InsufficientPermissionsException("Only the owner can make a folder public or not public");
439 Folder parent = folder.getParent();
440 if (folderName != null) {
442 if (!folder.getName().equals(folderName) && dao.existsFolderOrFile(parent.getId(), folderName))
443 throw new DuplicateNameException("A folder or file with the name '" + folderName + "' already exists at this level");
445 // Do the actual modification.
446 folder.setName(folderName);
448 if (permissions != null)
449 setFolderPermissions(user, folder, permissions);
450 if (readForAll != null)
451 setFolderReadForAll(user, folder, readForAll);
452 folder.getAuditInfo().setModificationDate(new Date());
453 folder.getAuditInfo().setModifiedBy(user);
455 touchParentFolders(folder, user, new Date());
456 return folder.getDTO();
460 public void createGroup(final Long userId, final String name) throws ObjectNotFoundException, DuplicateNameException {
463 throw new ObjectNotFoundException("No user specified");
464 if (StringUtils.isEmpty(name))
465 throw new ObjectNotFoundException("New group name is empty");
466 if (name.indexOf('/')>=0)
467 throw new IllegalArgumentException("Character '/' is not allowed in group name");
468 if (dao.existsGroup(userId, name))
469 throw new DuplicateNameException("A group with the name '" + name + "' already exists");
471 // TODO: Check permissions
473 final User owner = dao.getEntityById(User.class, userId);
475 // Do the actual work.
476 owner.createGroup(name);
480 public void deleteGroup(final Long userId, final Long groupId) throws ObjectNotFoundException, InsufficientPermissionsException {
483 throw new ObjectNotFoundException("No user specified");
485 throw new ObjectNotFoundException("No group specified");
487 // Do the actual work.
488 final User owner = dao.getEntityById(User.class, userId);
489 final Group group = dao.getEntityById(Group.class, groupId);
490 final Date now = new Date();
491 // Only delete the group if actually owned by the user.
492 if (group.getOwner().equals(owner)) {
493 List<Folder> folders = dao.getFoldersPermittedForGroup(userId, groupId);
494 for (Folder f : folders){
495 f.getPermissions().removeAll(group.getPermissions());
496 touchFolder(f, owner, now);
497 for(FileHeader file : f.getFiles()){
498 file.getPermissions().removeAll(group.getPermissions());
499 touchFile(file, owner, now);
502 List<FileHeader> files = dao.getFilesPermittedForGroup(userId, groupId);
503 for(FileHeader h : files){
504 h.getPermissions().removeAll(group.getPermissions());
505 touchFile(h, owner, now);
507 owner.removeSpecifiedGroup(group);
510 else throw new InsufficientPermissionsException("You are not the owner of this group");
514 public FileHeaderDTO createFile(Long userId, Long folderId, String name, String mimeType, InputStream stream)
515 throws DuplicateNameException, ObjectNotFoundException, GSSIOException,
516 InsufficientPermissionsException, QuotaExceededException {
519 file = uploadFile(stream, userId);
520 } catch ( IOException ioe) {
521 // Supply a more accurate problem description.
522 throw new GSSIOException("Problem creating file",ioe);
524 return createFile(userId, folderId, name, mimeType, file.length(), file.getAbsolutePath());
528 * @see gr.ebs.gss.server.ejb.ExternalAPIRemote#indexFile(java.lang.Long, boolean)
531 public void indexFile(Long fileId, boolean delete) {
532 Connection qConn = null;
533 Session session = null;
534 MessageProducer sender = null;
536 Context jndiCtx = new InitialContext();
537 ConnectionFactory factory = (QueueConnectionFactory) jndiCtx.lookup("java:/JmsXA");
538 Queue queue = (Queue) jndiCtx.lookup("queue/gss-indexingQueue");
539 qConn = factory.createConnection();
540 session = qConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
541 sender = session.createProducer(queue);
543 MapMessage map = session.createMapMessage();
544 map.setObject("id", fileId);
545 map.setBoolean("delete", delete);
548 catch (NamingException e) {
549 logger.error("Index was not updated: ", e);
551 catch (JMSException e) {
552 logger.error("Index was not updated: ", e);
563 catch (JMSException e) {
572 * A helper method that generates a unique file path for a stored file. The
573 * files are stored using random hash names that are distributed evenly in
574 * a 2-level tree of subdirectories named after the first two hex characters
575 * in the name. For example, file ab1234cd5769f will be stored in the path
576 * /file-repository-root/a/b/ab1234cd5769f. The directories will be created
577 * if they don't already exist.
579 * @return a unique new file path
581 private String generateRepositoryFilePath() {
582 String filename = Long.toHexString(random.nextLong());
583 String fileRepositoryPath = getConfiguration().getString("fileRepositoryPath","/tmp");
584 File root = new File(fileRepositoryPath);
587 File firstFolder = new File(root + File.separator + filename.substring(0, 1));
588 if (!firstFolder.exists())
590 File secondFolder = new File(firstFolder + File.separator + filename.substring(1, 2));
591 if (!secondFolder.exists())
592 secondFolder.mkdir();
593 return secondFolder + File.separator + filename;
597 public void deleteFile(final Long userId, final Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
600 throw new ObjectNotFoundException("No user specified");
602 throw new ObjectNotFoundException("No file specified");
604 // Do the actual work.
605 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
606 final Folder parent = file.getFolder();
608 throw new ObjectNotFoundException("The specified file has no parent folder");
609 final User user = dao.getEntityById(User.class, userId);
610 if (!file.hasDeletePermission(user))
611 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
612 for (final FileBody body : file.getBodies())
613 deleteActualFile(body.getStoredFilePath());
615 touchParentFolders(parent, user, new Date());
616 indexFile(fileId, true);
620 public void deleteActualFile(String path) {
623 File file = new File(path);
625 logger.error("Could not delete file " + path);
629 public void createTag(final Long userId, final Long fileHeaderId, final String tag) throws ObjectNotFoundException {
631 throw new ObjectNotFoundException("No user specified");
632 if (fileHeaderId == null)
633 throw new ObjectNotFoundException("No file specified");
634 if (StringUtils.isEmpty(tag))
635 throw new ObjectNotFoundException("Tag is empty");
637 final User user = dao.getEntityById(User.class, userId);
638 final FileHeader fh = dao.getEntityById(FileHeader.class, fileHeaderId);
639 final Folder parent = fh.getFolder();
641 throw new ObjectNotFoundException("The specified file has no parent folder");
642 user.addTag(fh, tag);
643 touchParentFolders(parent, user, new Date());
647 public Set<String> getUserTags(final Long userId) throws ObjectNotFoundException {
648 return dao.getUserTags(userId);
652 public void updateFile(Long userId, Long fileId, String name,
653 String tagSet, Date modificationDate, Boolean versioned,
654 Boolean readForAll, Set<PermissionDTO> permissions)
655 throws DuplicateNameException, ObjectNotFoundException, InsufficientPermissionsException {
657 throw new ObjectNotFoundException("No user specified");
659 throw new ObjectNotFoundException("No file specified");
660 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
661 final Folder parent = file.getFolder();
663 throw new ObjectNotFoundException("The specified file has no parent folder");
665 User user = dao.getEntityById(User.class, userId);
666 // Check permissions for modifying the file metadata.
667 if ((name != null || tagSet != null || modificationDate != null || versioned != null) && !file.hasWritePermission(user))
668 throw new InsufficientPermissionsException("User " + user.getId() + " cannot update file " + file.getName() + "(" + file.getId() + ")");
669 // Check permissions for making file public.
670 if (readForAll != null && !user.equals(file.getOwner()))
671 throw new InsufficientPermissionsException("Only the owner can make a file public or not public");
672 // Check permissions for modifying the ACL.
673 if(permissions != null && !permissions.isEmpty() && !file.hasModifyACLPermission(user))
674 throw new InsufficientPermissionsException("User " + user.getId() + " cannot update the permissions on file " + file.getName() + "(" + file.getId() + ")");
677 // Do plain check for file already exists.
678 // Extreme concurrency case should be caught by constraint violation later.
679 if (dao.existsFolderOrFile(parent.getId(), name)) throw new DuplicateNameException("A file or folder with the name '" + name + "' already exists");
683 if (modificationDate != null)
684 file.getAuditInfo().setModificationDate(modificationDate);
686 file.getAuditInfo().setModificationDate(new Date());
687 file.getAuditInfo().setModifiedBy(user);
689 List<FileTag> tags = file.getFileTags();
690 if (tagSet != null) {
691 Iterator<FileTag> i = tags.iterator();
692 while (i.hasNext()) {
693 FileTag tag = i.next();
700 StringTokenizer st = new StringTokenizer(tagSet, ",");
701 while (st.hasMoreTokens())
702 new FileTag(user, file, st.nextToken().trim());
704 if (versioned != null && !file.isVersioned() == versioned) {
705 if (file.isVersioned())
706 removeOldVersions(userId, fileId);
707 file.setVersioned(versioned);
709 if (readForAll != null && user.equals(file.getOwner()))
710 file.setReadForAll(readForAll);
711 if (permissions != null && !permissions.isEmpty())
712 setFilePermissions(file, permissions);
715 * Force constraint violation to manifest itself here.
716 * This should cover extreme concurrency cases that the simple check
717 * above hasn't caught.
722 catch (EJBTransactionRolledbackException e) {
723 Throwable cause = e.getCause();
724 if (cause instanceof PersistenceException && cause.getCause() instanceof ConstraintViolationException)
725 throw new DuplicateNameException("A file or folder with the name '" + name + "' already exists");
729 touchParentFolders(parent, user, new Date());
731 // Re-index the file if it was modified.
732 if (name != null || tagSet != null)
733 indexFile(fileId, false);
737 public InputStream getFileContents(Long userId, Long fileId)
738 throws ObjectNotFoundException, InsufficientPermissionsException {
740 throw new ObjectNotFoundException("No user specified");
742 throw new ObjectNotFoundException("No file specified");
744 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
745 User user = dao.getEntityById(User.class, userId);
746 if (!header.hasReadPermission(user)) {
747 logger.info("User " + user.getId() + " cannot read file " + header.getName() + "(" + fileId + ")");
748 throw new InsufficientPermissionsException("You don't have the necessary permissions");
751 File f = new File(header.getCurrentBody().getStoredFilePath());
753 return new FileInputStream(f);
754 } catch (FileNotFoundException e) {
755 logger.error("Could not locate the contents of file " + f.getAbsolutePath());
756 throw new ObjectNotFoundException("The file contents could not be located");
761 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFileContents(java.lang.Long, java.lang.Long, java.lang.Long)
764 public InputStream getFileContents(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
766 throw new ObjectNotFoundException("No user specified");
768 throw new ObjectNotFoundException("No file specified");
770 throw new ObjectNotFoundException("No file specified");
772 final FileHeader header = dao.getEntityById(FileHeader.class, fileId);
773 final FileBody body = dao.getEntityById(FileBody.class, bodyId);
774 final User user = dao.getEntityById(User.class, userId);
775 if (!header.hasReadPermission(user)) {
776 logger.info("User " + user.getId() + " cannot read file " + header.getName() + "(" + fileId + ")");
777 throw new InsufficientPermissionsException("You don't have the necessary permissions");
780 File f = new File(body.getStoredFilePath());
782 return new FileInputStream(f);
783 } catch (FileNotFoundException e) {
784 logger.error("Could not locate the contents of file " + f.getAbsolutePath());
785 throw new ObjectNotFoundException("The file contents could not be located");
790 public FileHeaderDTO getFile(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
792 throw new ObjectNotFoundException("No user specified");
794 throw new ObjectNotFoundException("No file specified");
795 final User user = dao.getEntityById(User.class, userId);
796 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
797 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
798 throw new InsufficientPermissionsException("You don't have the necessary permissions");
799 return file.getDTO();
803 public FileBodyDTO getFileBody(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
805 throw new ObjectNotFoundException("No user specified");
807 throw new ObjectNotFoundException("No file specified");
808 User user = dao.getEntityById(User.class, userId);
809 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
810 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
811 throw new InsufficientPermissionsException("You don't have the necessary permissions");
812 FileBody body = dao.getEntityById(FileBody.class, bodyId);
813 return body.getDTO();
817 public Object getResourceAtPath(Long ownerId, String path, boolean ignoreDeleted)
818 throws ObjectNotFoundException {
820 throw new ObjectNotFoundException("No user specified");
821 if (StringUtils.isEmpty(path))
822 throw new ObjectNotFoundException("No path specified");
824 User owner = dao.getEntityById(User.class, ownerId);
825 List<String> pathElements = new ArrayList<String>();
826 StringTokenizer st = new StringTokenizer(path, "/");
827 while (st.hasMoreTokens())
828 pathElements.add(st.nextToken());
829 if (pathElements.size() < 1)
830 return getRootFolder(owner.getId());
831 // Store the last element, since it requires special handling.
832 String lastElement = pathElements.remove(pathElements.size() - 1);
833 FolderDTO cursor = getRootFolder(owner.getId());
834 // Traverse and verify the specified folder path.
835 for (String pathElement : pathElements) {
836 cursor = getFolder(cursor.getId(), pathElement);
837 if (cursor.isDeleted())
838 throw new ObjectNotFoundException("Folder " + cursor.getPath() + " not found");
841 // Use the lastElement to retrieve the actual resource.
842 Object resource = null;
844 FileHeaderDTO file = getFile(cursor.getId(), lastElement);
845 if (ignoreDeleted && file.isDeleted())
846 throw new ObjectNotFoundException("Resource not found");
848 } catch (ObjectNotFoundException e) {
849 // Perhaps the requested resource is not a file, so
850 // check for folders as well.
851 FolderDTO folder = getFolder(cursor.getId(), lastElement);
852 if (ignoreDeleted && folder.isDeleted())
853 throw new ObjectNotFoundException("Resource not found");
860 * Retrieve a file for the specified user that has the specified name and
861 * its parent folder has id equal to folderId.
863 * @param userId the ID of the current user
864 * @param folderId the ID of the parent folder
865 * @param name the name of the requested file
866 * @return the file found
867 * @throws ObjectNotFoundException if the specified folder or file was not
868 * found, with the exception message mentioning the precise
871 private FileHeaderDTO getFile(Long folderId, String name) throws ObjectNotFoundException {
872 if (folderId == null)
873 throw new ObjectNotFoundException("No parent folder specified");
874 if (StringUtils.isEmpty(name))
875 throw new ObjectNotFoundException("No file specified");
877 FileHeader file = dao.getFile(folderId, name);
878 return file.getDTO();
882 * Retrieve a folder for the specified user that has the specified name and
883 * its parent folder has id equal to parentId.
885 * @param parentId the ID of the parent folder
886 * @param name the name of the requested folder
887 * @return the folder found
888 * @throws ObjectNotFoundException if the specified folder or parent was not
889 * found, with the exception message mentioning the precise
892 private FolderDTO getFolder(Long parentId, String name) throws ObjectNotFoundException {
893 if (parentId == null)
894 throw new ObjectNotFoundException("No parent folder specified");
895 if (StringUtils.isEmpty(name))
896 throw new ObjectNotFoundException("No folder specified");
898 Folder folder = dao.getFolder(parentId, name);
899 return folder.getDTO();
902 private FileHeaderDTO updateFileContents(Long userId, Long fileId, String mimeType, InputStream resourceInputStream) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
905 file = uploadFile(resourceInputStream, userId);
906 } catch ( IOException ioe) {
907 // Supply a more accurate problem description.
908 throw new GSSIOException("Problem creating file",ioe);
910 return updateFileContents(userId, fileId, mimeType, file.length(), file.getAbsolutePath());
914 public void copyFile(Long userId, Long fileId, String dest) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
916 throw new ObjectNotFoundException("No user specified");
918 throw new ObjectNotFoundException("No file specified");
919 if (StringUtils.isEmpty(dest))
920 throw new ObjectNotFoundException("No destination specified");
922 Object destination = getResourceAtPath(userId, getParentPath(dest), true);
923 if (!(destination instanceof FolderDTO))
924 throw new ObjectNotFoundException("Destination parent folder not found");
925 FolderDTO parent = (FolderDTO) destination;
926 copyFile(userId, fileId, parent.getId(), getLastElement(dest));
930 public void copyFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
932 throw new ObjectNotFoundException("No user specified");
934 throw new ObjectNotFoundException("No owner specified");
936 throw new ObjectNotFoundException("No file specified");
937 if (StringUtils.isEmpty(dest))
938 throw new ObjectNotFoundException("No destination specified");
940 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
941 if (!(destination instanceof FolderDTO))
942 throw new ObjectNotFoundException("Destination parent folder not found");
943 FolderDTO parent = (FolderDTO) destination;
944 copyFile(userId, fileId, parent.getId(), getLastElement(dest));
948 public void copyFile(Long userId, Long fileId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
950 throw new ObjectNotFoundException("No user specified");
952 throw new ObjectNotFoundException("No file specified");
954 throw new ObjectNotFoundException("No destination specified");
955 if (StringUtils.isEmpty(destName))
956 throw new ObjectNotFoundException("No destination file name specified");
958 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
959 Folder destination = dao.getEntityById(Folder.class, destId);
960 User user = dao.getEntityById(User.class, userId);
961 if (!file.hasReadPermission(user) || !destination.hasWritePermission(user))
962 throw new InsufficientPermissionsException("You don't have the necessary permissions");
963 boolean versioned = file.isVersioned();
964 int versionsNumber = file.getBodies().size();
965 FileBody oldestBody = file.getBodies().get(0);
966 assert oldestBody != null;
967 File contents = new File(oldestBody.getStoredFilePath());
969 createFile(user.getId(), destination.getId(), destName, oldestBody.getMimeType(), new FileInputStream(contents));
970 FileHeader copiedFile = dao.getFile(destination.getId(), destName);
971 copiedFile.setVersioned(versioned);
973 if (versionsNumber > 1)
974 for (int i = 1; i < versionsNumber; i++) {
975 FileBody body = file.getBodies().get(i);
977 contents = new File(body.getStoredFilePath());
978 updateFileContents(user.getId(), copiedFile.getId(), body.getMimeType(), new FileInputStream(contents));
980 List<FileTag> tags = file.getFileTags();
981 for (FileTag tag : tags)
982 createTag(userId, copiedFile.getId(), tag.getTag());
984 } catch (FileNotFoundException e) {
985 throw new ObjectNotFoundException("File contents not found for file " + contents.getAbsolutePath());
991 public void copyFolder(Long userId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
993 throw new ObjectNotFoundException("No user specified");
994 if (folderId == null)
995 throw new ObjectNotFoundException("No folder specified");
996 if (StringUtils.isEmpty(dest))
997 throw new ObjectNotFoundException("No destination specified");
999 Object destination = getResourceAtPath(userId, getParentPath(dest), true);
1000 if (!(destination instanceof FolderDTO))
1001 throw new ObjectNotFoundException("Destination folder not found");
1002 FolderDTO parent = (FolderDTO) destination;
1003 copyFolder(userId, folderId, parent.getId(), getLastElement(dest));
1007 public void copyFolder(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
1009 throw new ObjectNotFoundException("No user specified");
1010 if (folderId == null)
1011 throw new ObjectNotFoundException("No folder specified");
1013 throw new ObjectNotFoundException("No destination specified");
1014 if (StringUtils.isEmpty(destName))
1015 throw new ObjectNotFoundException("No destination folder name specified");
1016 Folder folder = dao.getEntityById(Folder.class, folderId);
1017 Folder destination = dao.getEntityById(Folder.class, destId);
1018 User user = dao.getEntityById(User.class, userId);
1019 if (!destination.hasWritePermission(user) || !folder.hasReadPermission(user))
1020 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1021 createFolder(user.getId(), destination.getId(), destName);
1025 public void copyFolderStructureToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1027 throw new ObjectNotFoundException("No user specified");
1028 if (ownerId == null)
1029 throw new ObjectNotFoundException("No owner specified");
1030 if (folderId == null)
1031 throw new ObjectNotFoundException("No folder specified");
1032 if (StringUtils.isEmpty(dest))
1033 throw new ObjectNotFoundException("No destination specified");
1035 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1036 if (!(destination instanceof FolderDTO))
1037 throw new ObjectNotFoundException("Destination folder not found");
1038 FolderDTO parent = (FolderDTO) destination;
1039 copyFolderStructure(userId, folderId, parent.getId(), getLastElement(dest));
1043 public void copyFolderStructure(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1045 throw new ObjectNotFoundException("No user specified");
1046 if (folderId == null)
1047 throw new ObjectNotFoundException("No folder specified");
1049 throw new ObjectNotFoundException("No destination specified");
1050 if (StringUtils.isEmpty(destName))
1051 throw new ObjectNotFoundException("No destination folder name specified");
1053 Folder folder = dao.getEntityById(Folder.class, folderId);
1054 Folder destination = dao.getEntityById(Folder.class, destId);
1055 final User user = dao.getEntityById(User.class, userId);
1056 // XXX: quick fix need to copy only visible items to user (Source
1058 if (!folder.getOwner().getId().equals(userId) && !folder.hasReadPermission(user))
1060 if(folder.isDeleted())//do not copy trashed folder and contents
1062 if (!destination.hasWritePermission(user) || !folder.hasReadPermission(user))
1063 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1064 createFolder(user.getId(), destination.getId(), destName);
1065 Folder createdFolder = dao.getFolder(destination.getId(), destName);
1066 List<FileHeader> files = folder.getFiles();
1068 for (FileHeader file : files)
1069 if(!file.isDeleted())
1070 copyFile(userId, file.getId(), createdFolder.getId(), file.getName());
1071 List<Folder> subFolders = folder.getSubfolders();
1072 if (subFolders != null)
1073 for (Folder sub : subFolders)
1074 if(!sub.getId().equals(createdFolder.getId()))
1075 copyFolderStructure(userId, sub.getId(), createdFolder.getId(), sub.getName());
1080 * For a provided path, remove the last element and return the rest, that is
1081 * the path of the parent folder.
1083 * @param path the specified path
1084 * @return the path of the parent folder
1085 * @throws ObjectNotFoundException if the provided string contains no path
1088 private String getParentPath(String path) throws ObjectNotFoundException {
1089 int lastDelimiter = path.lastIndexOf('/');
1090 if (lastDelimiter == 0)
1092 if (lastDelimiter == -1)
1094 throw new ObjectNotFoundException("There is no parent in the path: " + path);
1095 else if (lastDelimiter < path.length() - 1)
1096 // Return the part before the delimiter.
1097 return path.substring(0, lastDelimiter);
1099 // Remove the trailing delimiter and then recurse.
1100 String strippedTrail = path.substring(0, lastDelimiter);
1101 return getParentPath(strippedTrail);
1106 * Get the last element in a path that denotes the file or folder name.
1108 * @param path the provided path
1109 * @return the last element in the path
1111 private String getLastElement(String path) {
1112 int lastDelimiter = path.lastIndexOf('/');
1113 if (lastDelimiter == -1)
1116 else if (lastDelimiter < path.length() - 1)
1117 // Return the part after the delimiter.
1118 return path.substring(lastDelimiter + 1);
1120 // Remove the trailing delimiter and then recurse.
1121 String strippedTrail = path.substring(0, lastDelimiter);
1122 return getLastElement(strippedTrail);
1127 public void moveFileToTrash(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1129 throw new ObjectNotFoundException("No user specified");
1131 throw new ObjectNotFoundException("No file specified");
1133 // Do the actual work.
1134 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1135 Folder parent = file.getFolder();
1137 throw new ObjectNotFoundException("The specified file has no parent folder");
1138 User user = dao.getEntityById(User.class, userId);
1139 if (!file.hasDeletePermission(user))
1140 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
1142 file.setDeleted(true);
1144 touchParentFolders(parent, user, new Date());
1148 public void moveFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, InsufficientPermissionsException, QuotaExceededException {
1150 throw new ObjectNotFoundException("No user specified");
1151 if (ownerId == null)
1152 throw new ObjectNotFoundException("No owner specified");
1154 throw new ObjectNotFoundException("No file specified");
1155 if (StringUtils.isEmpty(dest))
1156 throw new ObjectNotFoundException("No destination specified");
1158 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1159 if (!(destination instanceof FolderDTO))
1160 throw new ObjectNotFoundException("Destination parent folder not found");
1161 FolderDTO parent = (FolderDTO) destination;
1162 moveFile(userId, fileId, parent.getId(), getLastElement(dest));
1166 public void moveFile(Long userId, Long fileId, Long destId, String destName) throws InsufficientPermissionsException, ObjectNotFoundException, QuotaExceededException {
1168 throw new ObjectNotFoundException("No user specified");
1170 throw new ObjectNotFoundException("No file specified");
1172 throw new ObjectNotFoundException("No destination specified");
1173 if (StringUtils.isEmpty(destName))
1174 throw new ObjectNotFoundException("No destination file name specified");
1176 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1177 Folder source = file.getFolder();
1178 Folder destination = dao.getEntityById(Folder.class, destId);
1180 User owner = dao.getEntityById(User.class, userId);
1181 if (!file.hasDeletePermission(owner) || !destination.hasWritePermission(owner))
1182 throw new InsufficientPermissionsException("User " + owner.getId() + " cannot move file " + file.getName() + "(" + file.getId() + ")");
1184 // if the destination folder belongs to another user:
1185 if (!file.getOwner().equals(destination.getOwner())) {
1186 // (a) check if the destination quota allows the move
1187 if(getQuotaLeft(destination.getOwner().getId()) < file.getTotalSize())
1188 throw new QuotaExceededException("Not enough free space available");
1189 User newOwner = destination.getOwner();
1190 // (b) if quota OK, change the owner of the file
1191 file.setOwner(newOwner);
1192 // if the file has no permission for the new owner, add it
1193 Permission ownerPermission = null;
1194 for (final Permission p : file.getPermissions())
1195 if (p.getUser() != null)
1196 if (p.getUser().equals(newOwner)) {
1197 ownerPermission = p;
1200 if (ownerPermission == null) {
1201 ownerPermission = new Permission();
1202 ownerPermission.setUser(newOwner);
1203 file.addPermission(ownerPermission);
1205 ownerPermission.setRead(true);
1206 ownerPermission.setWrite(true);
1207 ownerPermission.setModifyACL(true);
1209 // move the file to the destination folder
1210 file.setFolder(destination);
1211 touchParentFolders(source, owner, new Date());
1212 touchParentFolders(destination, owner, new Date());
1216 public void moveFolderToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, InsufficientPermissionsException, QuotaExceededException {
1218 throw new ObjectNotFoundException("No user specified");
1219 if (ownerId == null)
1220 throw new ObjectNotFoundException("No owner specified");
1221 if (folderId == null)
1222 throw new ObjectNotFoundException("No folder specified");
1223 if (StringUtils.isEmpty(dest))
1224 throw new ObjectNotFoundException("No destination specified");
1226 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1227 if (!(destination instanceof FolderDTO))
1228 throw new ObjectNotFoundException("Destination parent folder not found");
1229 FolderDTO parent = (FolderDTO) destination;
1230 moveFolder(userId, folderId, parent.getId(), getLastElement(dest));
1234 public void moveFolder(Long userId, Long folderId, Long destId, String destName)
1235 throws ObjectNotFoundException, InsufficientPermissionsException,
1236 QuotaExceededException {
1237 Folder source = dao.getEntityById(Folder.class, folderId);
1238 Folder destination = dao.getEntityById(Folder.class, destId);
1239 User user = dao.getEntityById(User.class, userId);
1240 User sourceOwner = source.getOwner();
1241 User destinationOwner = destination.getOwner();
1242 // Do not move trashed folders and contents.
1243 if (source.isDeleted())
1245 // Check permissions.
1246 if (!destination.hasWritePermission(user)
1247 || !source.hasReadPermission(user)
1248 || !source.hasWritePermission(user))
1249 throw new InsufficientPermissionsException("You don't have the " +
1250 "necessary permissions");
1251 // Use the same timestamp for all subsequent modifications to make
1252 // changes appear simultaneous.
1253 Date now = new Date();
1254 // If source and destination are not in the same user's namespace,
1255 // change owners and check quota.
1256 if (!sourceOwner.equals(destinationOwner)) {
1257 changeOwner(source, destinationOwner, user, now);
1258 if (getQuotaLeft(destinationOwner.getId()) < 0)
1259 throw new QuotaExceededException("Not enough free space " +
1260 "available in destination folder");
1262 // Perform the move.
1263 Folder oldParent = source.getParent();
1264 oldParent.removeSubfolder(source);
1265 destination.addSubfolder(source);
1266 // Mark the former parent and destination trees upwards as modified.
1267 touchParentFolders(oldParent, user, now);
1268 touchParentFolders(source, user, now);
1272 * Recursively change the owner of the specified folder and all of its
1273 * contents to the specified owner. Also mark them all as modified with the
1274 * specified modifier and modificationDate.
1276 private void changeOwner(Folder folder, User owner, User modifier, Date modificationDate) {
1277 for (FileHeader file: folder.getFiles()) {
1278 file.setOwner(owner);
1279 file.getAuditInfo().setModificationDate(modificationDate);
1280 file.getAuditInfo().setModifiedBy(modifier);
1282 for (Folder sub: folder.getSubfolders())
1283 changeOwner(sub, owner, modifier, modificationDate);
1284 folder.setOwner(owner);
1285 folder.getAuditInfo().setModificationDate(modificationDate);
1286 folder.getAuditInfo().setModifiedBy(modifier);
1290 public List<FileHeaderDTO> getDeletedFiles(Long userId) throws ObjectNotFoundException {
1293 throw new ObjectNotFoundException("No user specified");
1295 // Do the actual work.
1296 final List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1297 final List<FileHeader> files = dao.getDeletedFiles(userId);
1298 for (final FileHeader f : files)
1299 result.add(f.getDTO());
1304 public void removeFileFromTrash(Long userId, Long fileId)
1305 throws ObjectNotFoundException, InsufficientPermissionsException {
1307 throw new ObjectNotFoundException("No user specified");
1309 throw new ObjectNotFoundException("No file specified");
1311 // Do the actual work.
1312 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1313 Folder parent = file.getFolder();
1315 throw new ObjectNotFoundException("The specified file has no parent folder");
1316 User user = dao.getEntityById(User.class, userId);
1317 if (!file.hasDeletePermission(user))
1318 throw new InsufficientPermissionsException("User " + user.getUsername() +
1319 " cannot restore file " + file.getName());
1321 file.setDeleted(false);
1323 touchParentFolders(parent, user, new Date());
1327 public void moveFolderToTrash(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
1329 throw new ObjectNotFoundException("No user specified");
1330 if (folderId == null)
1331 throw new ObjectNotFoundException("No folder specified");
1332 Folder folder = dao.getEntityById(Folder.class, folderId);
1333 User user = dao.getEntityById(User.class, userId);
1334 if (!folder.hasDeletePermission(user))
1335 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1336 folder.setDeleted(true);
1338 touchParentFolders(folder, user, new Date());
1339 for (FileHeader file : folder.getFiles())
1340 moveFileToTrash(userId, file.getId());
1341 for (Folder subFolder : folder.getSubfolders())
1342 moveFolderToTrash(userId, subFolder.getId());
1347 public void removeFolderFromTrash(Long userId, Long folderId)
1348 throws ObjectNotFoundException, InsufficientPermissionsException {
1350 throw new ObjectNotFoundException("No user specified");
1351 if (folderId == null)
1352 throw new ObjectNotFoundException("No folder specified");
1353 Folder folder = dao.getEntityById(Folder.class, folderId);
1354 User user = dao.getEntityById(User.class, userId);
1355 if (!folder.hasDeletePermission(user))
1356 throw new InsufficientPermissionsException("User " + user.getUsername() +
1357 " cannot restore folder " + folder.getName());
1358 folder.setDeleted(false);
1359 for (FileHeader file : folder.getFiles())
1360 removeFileFromTrash(userId, file.getId());
1361 for (Folder subFolder : folder.getSubfolders())
1362 removeFolderFromTrash(userId, subFolder.getId());
1364 touchParentFolders(folder, user, new Date());
1368 public List<FolderDTO> getDeletedRootFolders(Long userId) throws ObjectNotFoundException {
1369 List<Folder> folders = dao.getDeletedRootFolders(userId);
1370 List<FolderDTO> result = new ArrayList<FolderDTO>();
1371 for (Folder folder : folders)
1372 result.add(folder.getDTO());
1377 public void emptyTrash(Long userId) throws ObjectNotFoundException, InsufficientPermissionsException {
1378 List<FolderDTO> deletedRootFolders = getDeletedRootFolders(userId);
1379 for (FolderDTO fdto : deletedRootFolders)
1380 deleteFolder(userId, fdto.getId());
1381 List<FileHeaderDTO> deletedFiles = getDeletedFiles(userId);
1382 for (FileHeaderDTO filedto : deletedFiles)
1383 deleteFile(userId, filedto.getId());
1387 public void restoreTrash(Long userId) throws ObjectNotFoundException, InsufficientPermissionsException {
1388 List<FolderDTO> deletedRootFolders = getDeletedRootFolders(userId);
1389 for (FolderDTO fdto : deletedRootFolders)
1390 removeFolderFromTrash(userId, fdto.getId());
1391 List<FileHeaderDTO> deletedFiles = getDeletedFiles(userId);
1392 for (FileHeaderDTO filedto : deletedFiles)
1393 removeFileFromTrash(userId, filedto.getId());
1397 public User createUser(String username, String name, String mail,
1398 String idp, String idpid) throws ObjectNotFoundException {
1399 if (username == null)
1400 throw new ObjectNotFoundException("No username specified");
1402 throw new ObjectNotFoundException("No name specified");
1404 User user = new User();
1405 user.setUsername(username);
1407 user.setEmail(mail);
1408 user.setIdentityProvider(idp);
1409 user.setIdentityProviderId(idpid);
1410 Date now = new Date();
1411 AuditInfo auditInfo = new AuditInfo();
1412 auditInfo.setCreationDate(now);
1413 auditInfo.setModificationDate(now);
1414 user.setAuditInfo(auditInfo);
1415 user.setActive(true);
1416 user.generateAuthToken();
1417 user.generateWebDAVPassword();
1418 user.setUserClass(getDefaultUserClass());
1420 // Make sure we get an ID in the user object.
1422 // Create the root folder for the user.
1423 createFolder(user.getName(), null, user);
1428 * Get the default user class, which is the one with the lowest quota.
1430 private UserClass getDefaultUserClass() {
1431 return getUserClasses().get(0);
1435 public List<UserClass> getUserClasses() {
1436 List<UserClass> classes = dao.getUserClasses();
1437 // Create a default user class for first-time use. Afterwards, the
1438 // admin should modify or add to the userclass table.
1439 if (classes.size() == 0) {
1440 UserClass defaultClass = new UserClass();
1441 defaultClass.setName("default");
1442 Long defaultQuota = getConfiguration().getLong("quota", new Long(52428800L));
1443 defaultClass.setQuota(defaultQuota);
1444 dao.create(defaultClass);
1445 classes.add(defaultClass);
1451 public User findUserByEmail(String email) {
1452 return dao.findUserByEmail(email);
1456 public void updateUser(User user) {
1461 public User findUser(String username) {
1462 if (username == null)
1464 return dao.findUser(username);
1468 public User updateUserToken(Long userId) throws ObjectNotFoundException {
1470 throw new ObjectNotFoundException("No user specified");
1471 User user = dao.getEntityById(User.class, userId);
1472 user.generateAuthToken();
1477 public Set<PermissionDTO> getFolderPermissions(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
1479 throw new ObjectNotFoundException("No user specified");
1480 if (folderId == null)
1481 throw new ObjectNotFoundException("No folder specified");
1482 User user = dao.getEntityById(User.class, userId);
1483 Folder folder = dao.getEntityById(Folder.class, folderId);
1484 if(!folder.hasReadPermission(user))
1485 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1486 Set<Permission> perms = folder.getPermissions();
1487 Set<PermissionDTO> result = new LinkedHashSet<PermissionDTO>();
1488 for (Permission perm : perms)
1489 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId()))
1490 result.add(perm.getDTO());
1491 for (Permission perm : perms)
1492 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId())) {
1494 result.add(perm.getDTO());
1500 * Set the provided permissions as the new permissions of the specified
1505 * @param permissions
1506 * @throws ObjectNotFoundException
1507 * @throws InsufficientPermissionsException
1509 private void setFolderPermissions(User user, Folder folder, Set<PermissionDTO> permissions) throws ObjectNotFoundException, InsufficientPermissionsException {
1510 if (permissions != null && !permissions.isEmpty()) {
1511 User owner = folder.getOwner();
1512 PermissionDTO ownerPerm = null;
1513 for (PermissionDTO dto : permissions)
1514 if (dto.getUser() != null && dto.getUser().getId().equals(owner.getId())) {
1518 if (ownerPerm == null || !ownerPerm.hasRead() || !ownerPerm.hasWrite() || !ownerPerm.hasModifyACL())
1519 throw new InsufficientPermissionsException("Can't remove permissions from owner");
1520 // Delete previous entries
1521 for (Permission perm: folder.getPermissions())
1523 folder.getPermissions().clear();
1524 for (PermissionDTO dto : permissions) {
1525 // Skip 'empty' permission entries.
1526 if (!dto.getRead() && !dto.getWrite() && !dto.getModifyACL()) continue;
1527 folder.addPermission(getPermission(dto));
1530 for (FileHeader file : folder.getFiles()) {
1531 setFilePermissions(file, permissions);
1532 Date now = new Date();
1533 file.getAuditInfo().setModificationDate(now);
1534 file.getAuditInfo().setModifiedBy(user);
1536 for (Folder sub : folder.getSubfolders())
1537 setFolderPermissions(user, sub, permissions);
1541 private Permission getPermission(PermissionDTO dto) throws ObjectNotFoundException {
1542 Permission res = new Permission();
1543 if (dto.getGroup() != null)
1544 res.setGroup(dao.getEntityById(Group.class, dto.getGroup().getId()));
1545 else if (dto.getUser() != null)
1546 if (dto.getUser().getId() == null)
1547 res.setUser(dao.getUser(dto.getUser().getUsername()));
1549 res.setUser(dao.getEntityById(User.class, dto.getUser().getId()));
1550 res.setRead(dto.hasRead());
1551 res.setWrite(dto.hasWrite());
1552 res.setModifyACL(dto.hasModifyACL());
1557 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsersByUserNameLike(java.lang.String)
1560 public List<UserDTO> getUsersByUserNameLike(String username) {
1561 List<User> users = dao.getUsersByUserNameLike(username);
1562 List<UserDTO> result = new ArrayList<UserDTO>();
1563 for (User u : users)
1564 result.add(u.getDTO());
1570 public void addUserToGroup(Long userId, Long groupId, Long userToAddId) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
1572 throw new ObjectNotFoundException("No user specified");
1573 if (groupId == null)
1574 throw new ObjectNotFoundException("No group specified");
1575 if (userToAddId == null)
1576 throw new ObjectNotFoundException("No user to add specified");
1577 User user = dao.getEntityById(User.class, userId);
1578 Group group = dao.getEntityById(Group.class, groupId);
1579 if (!group.getOwner().equals(user))
1580 throw new InsufficientPermissionsException();
1581 User userToAdd = dao.getEntityById(User.class, userToAddId);
1582 if (group.contains(userToAdd))
1583 throw new DuplicateNameException("User already exists in group");
1584 group.getMembers().add(userToAdd);
1590 public void invalidateUserToken(Long userId) throws ObjectNotFoundException {
1592 throw new ObjectNotFoundException("No user specified");
1593 User user = dao.getEntityById(User.class, userId);
1594 user.invalidateAuthToken();
1599 public List<FolderDTO> getSharedRootFolders(Long userId) throws ObjectNotFoundException {
1601 throw new ObjectNotFoundException("No user specified");
1602 List<Folder> folders = dao.getSharedRootFolders(userId);
1603 List<FolderDTO> result = new ArrayList<FolderDTO>();
1604 for (Folder f : folders) {
1605 FolderDTO dto = f.getDTO();
1606 dto.setSubfolders(getSharedSubfolders(userId, f.getId()));
1613 public void removeMemberFromGroup(Long userId, Long groupId, Long memberId) throws ObjectNotFoundException, InsufficientPermissionsException {
1615 throw new ObjectNotFoundException("No user specified");
1616 if (groupId == null)
1617 throw new ObjectNotFoundException("No group specified");
1618 if (memberId == null)
1619 throw new ObjectNotFoundException("No member specified");
1620 User owner = dao.getEntityById(User.class, userId);
1621 Group group = dao.getEntityById(Group.class, groupId);
1622 User member = dao.getEntityById(User.class, memberId);
1623 if (!group.getOwner().equals(owner))
1624 throw new InsufficientPermissionsException("User is not the owner of the group");
1625 group.removeMemberFromGroup(member);
1631 public List<UserDTO> getUsersSharingFoldersForUser(Long userId) throws ObjectNotFoundException {
1632 List<User> users = dao.getUsersSharingFoldersForUser(userId);
1633 List<User> usersFiles = dao.getUsersSharingFilesForUser(userId);
1634 List<UserDTO> res = new ArrayList<UserDTO>();
1635 for (User u : users)
1636 res.add(u.getDTO());
1637 for(User fu : usersFiles)
1638 if(!users.contains(fu))
1639 res.add(fu.getDTO());
1644 public Set<PermissionDTO> getFilePermissions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1646 throw new ObjectNotFoundException("No user specified");
1648 throw new ObjectNotFoundException("No folder specified");
1649 User user = dao.getEntityById(User.class, userId);
1650 FileHeader folder = dao.getEntityById(FileHeader.class, fileId);
1651 if(!folder.hasReadPermission(user))
1652 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1653 Set<Permission> perms = folder.getPermissions();
1654 Set<PermissionDTO> result = new LinkedHashSet<PermissionDTO>();
1655 for (Permission perm : perms)
1656 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId()))
1657 result.add(perm.getDTO());
1658 for (Permission perm : perms)
1659 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId())) {
1661 result.add(perm.getDTO());
1666 * Set the provided permissions as the new permissions of the specified
1667 * file. This method sets the modification date/user attributes to the
1668 * current values as a side effect.
1671 * @param permissions
1672 * @throws ObjectNotFoundException
1673 * @throws InsufficientPermissionsException
1675 private void setFilePermissions(FileHeader file,
1676 Set<PermissionDTO> permissions)
1677 throws ObjectNotFoundException, InsufficientPermissionsException {
1678 if (permissions != null && !permissions.isEmpty()) {
1679 PermissionDTO ownerPerm = null;
1680 for (PermissionDTO dto : permissions)
1681 if (dto.getUser() != null && dto.getUser().getId().equals(file.getOwner().getId())) {
1685 if (ownerPerm == null || !ownerPerm.hasRead() || !ownerPerm.hasWrite() || !ownerPerm.hasModifyACL())
1686 throw new InsufficientPermissionsException("Can't remove permissions from owner");
1687 // Delete previous entries.
1688 for (Permission perm: file.getPermissions())
1690 file.getPermissions().clear();
1691 for (PermissionDTO dto : permissions) {
1692 // Skip 'empty' permission entries.
1693 if (!dto.getRead() && !dto.getWrite() && !dto.getModifyACL()) continue;
1694 file.addPermission(getPermission(dto));
1701 public List<FileHeaderDTO> getSharedFilesNotInSharedFolders(Long userId) throws ObjectNotFoundException {
1703 throw new ObjectNotFoundException("No user specified");
1704 List<FileHeader> files = dao.getSharedFilesNotInSharedFolders(userId);
1705 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1706 for (FileHeader f : files)
1707 result.add(f.getDTO());
1712 public List<FileHeaderDTO> getSharedFiles(Long userId) throws ObjectNotFoundException {
1714 throw new ObjectNotFoundException("No user specified");
1715 List<FileHeader> files = dao.getSharedFiles(userId);
1716 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1717 for (FileHeader f : files)
1718 result.add(f.getDTO());
1723 public List<FolderDTO> getSharedFolders(Long userId) throws ObjectNotFoundException {
1725 throw new ObjectNotFoundException("No user specified");
1726 List<Folder> folders = dao.getSharedFolders(userId);
1727 List<FolderDTO> result = new ArrayList<FolderDTO>();
1728 for (Folder f : folders)
1729 result.add(f.getDTO());
1734 public List<FileHeaderDTO> getSharedFiles(Long ownerId, Long callingUserId) throws ObjectNotFoundException {
1735 if (ownerId == null)
1736 throw new ObjectNotFoundException("No owner specified");
1737 if (callingUserId == null)
1738 throw new ObjectNotFoundException("No calling user specified");
1739 List<FileHeader> folders = dao.getSharedFiles(ownerId, callingUserId);
1740 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1741 for (FileHeader f : folders)
1742 result.add(f.getDTO());
1747 public List<FolderDTO> getSharedRootFolders(Long ownerId, Long callingUserId) throws ObjectNotFoundException {
1748 if (ownerId == null)
1749 throw new ObjectNotFoundException("No owner specified");
1750 if (callingUserId == null)
1751 throw new ObjectNotFoundException("No calling user specified");
1752 List<Folder> folders = dao.getSharedRootFolders(ownerId, callingUserId);
1753 List<FolderDTO> result = new ArrayList<FolderDTO>();
1754 for (Folder f : folders) {
1755 FolderDTO dto = f.getDTO();
1756 dto.setSubfolders(getSharedSubfolders(ownerId, callingUserId, f.getId()));
1764 public List<FolderDTO> getSharedSubfolders(Long userId, Long folderId) throws ObjectNotFoundException {
1766 throw new ObjectNotFoundException("No user specified");
1767 if (folderId == null)
1768 throw new ObjectNotFoundException("No folder specified");
1769 User user = dao.getEntityById(User.class, userId);
1770 Folder folder = dao.getEntityById(Folder.class, folderId);
1771 List<FolderDTO> result = new ArrayList<FolderDTO>();
1772 if (folder.isShared(user) || folder.isReadForAll())
1773 for (Folder f : folder.getSubfolders())
1774 if ((f.isShared(user) || f.isReadForAll()) && !f.isDeleted())
1775 result.add(f.getDTO());
1780 public List<FolderDTO> getSharedSubfolders(Long userId, Long callingUserId, Long folderId) throws ObjectNotFoundException {
1782 throw new ObjectNotFoundException("No user specified");
1783 if (callingUserId == null)
1784 throw new ObjectNotFoundException("No user specified");
1785 if (folderId == null)
1786 throw new ObjectNotFoundException("No folder specified");
1787 User user = dao.getEntityById(User.class, callingUserId);
1788 Folder folder = dao.getEntityById(Folder.class, folderId);
1789 List<FolderDTO> result = new ArrayList<FolderDTO>();
1790 if (folder.isSharedForOtherUser(user))
1791 for (Folder f : folder.getSubfolders())
1792 if (f.isSharedForOtherUser(user) && !f.isDeleted()){
1793 FolderDTO dto = f.getDTO();
1794 dto.setSubfolders(getSharedSubfolders(userId, callingUserId, dto.getId()));
1802 public List<FileHeaderDTO> searchFiles(Long userId, String query) throws ObjectNotFoundException {
1804 throw new ObjectNotFoundException("No user specified");
1805 User user = getUser(userId);
1807 throw new ObjectNotFoundException("No query specified");
1808 List<FileHeader> files = search(user.getId(), query);
1809 List<FileHeaderDTO> res = new ArrayList<FileHeaderDTO>();
1810 for(FileHeader f : files)
1811 res.add(f.getDTO());
1816 * Performs the actuals search on the solr server and returns the results
1818 * We have to use the dismax query type (instead of the
1819 * standard) because it allows for search time field boosting. This is because we can't use indexing
1820 * time field boosting due to the patched rich indexing API that does not allow it
1824 * @return a List of FileHeader objects
1826 private List<FileHeader> search(Long userId, String query) {
1828 HttpClient httpClient = new HttpClient();
1830 GetMethod method = new GetMethod(getConfiguration().getString("solrSelectUrl"));
1831 NameValuePair[] params = {new NameValuePair("qt", "dismax"),
1832 new NameValuePair("q", query),
1833 new NameValuePair("sort", "score desc"),
1834 new NameValuePair("indent", "on")};
1835 method.setQueryString(params);
1838 String response = null;
1840 statusCode = httpClient.executeMethod(method);
1841 logger.debug("HTTP status: " + statusCode);
1842 response = method.getResponseBodyAsString();
1843 logger.debug(response);
1845 if (statusCode != 200 && retryCount < 3)
1847 Thread.sleep(3000); //Give Solr a little time to be available
1848 } catch (InterruptedException e) {
1850 } while (statusCode != 200 && retryCount < 3);
1851 if (statusCode != 200)
1852 throw new EJBException("Search query return error:\n" + response);
1854 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
1855 DocumentBuilder db = dbf.newDocumentBuilder();
1856 Document doc = db.parse(method.getResponseBodyAsStream());
1857 method.releaseConnection();
1859 Node root = doc.getElementsByTagName("response").item(0);
1860 Node lst = root.getFirstChild().getNextSibling();
1861 Node status = lst.getFirstChild().getNextSibling();
1862 if (status.getAttributes().getNamedItem("name").getNodeValue().equals("status") &&
1863 status.getTextContent().equals("0")) {
1864 List<FileHeader> fileResult = new ArrayList<FileHeader>();
1865 Node result = lst.getNextSibling().getNextSibling();
1866 NodeList docs = result.getChildNodes();
1867 User user = getUser(userId);
1868 for (int i=1; i<docs.getLength(); i=i+2) {
1869 Node d = docs.item(i);
1870 NodeList docData = d.getChildNodes();
1871 for (int j=1; j<docData.getLength(); j=j+2) {
1872 Node dd = docData.item(j);
1873 if (dd.getAttributes().item(0).getNodeName().equals("name") &&
1874 dd.getAttributes().item(0).getNodeValue().equals("id")) {
1875 Long fileId = Long.valueOf(dd.getTextContent());
1877 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1878 if (file.hasReadPermission(user)) {
1879 fileResult.add(file);
1880 logger.debug("File added " + fileId);
1882 } catch (ObjectNotFoundException e) {
1883 logger.warn("Search result not found", e);
1890 throw new EJBException();
1891 } catch (HttpException e) {
1892 throw new EJBException(e);
1893 } catch (IOException e) {
1894 throw new EJBException(e);
1895 } catch (SAXException e) {
1896 throw new EJBException(e);
1897 } catch (ParserConfigurationException e) {
1898 throw new EJBException(e);
1899 } catch (ObjectNotFoundException e) {
1900 throw new EJBException(e);
1905 public void copyFiles(Long userId, List<Long> fileIds, Long destId) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
1906 for(Long l : fileIds){
1907 FileHeader file = dao.getEntityById(FileHeader.class, l);
1908 copyFile(userId, l, destId, file.getName());
1915 public void moveFiles(Long userId, List<Long> fileIds, Long destId) throws InsufficientPermissionsException, ObjectNotFoundException, QuotaExceededException {
1916 for(Long l : fileIds){
1917 FileHeader file = dao.getEntityById(FileHeader.class, l);
1918 moveFile(userId, l, destId, file.getName());
1924 public void deleteFiles(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1926 throw new ObjectNotFoundException("No user specified");
1927 final User user = dao.getEntityById(User.class, userId);
1928 List<String> filesToRemove = new ArrayList<String>();
1929 //first delete database objects
1930 for(Long fileId : fileIds){
1932 throw new ObjectNotFoundException("No file specified");
1933 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1934 final Folder parent = file.getFolder();
1936 throw new ObjectNotFoundException("The specified file has no parent folder");
1937 if (!file.hasDeletePermission(user))
1938 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
1940 parent.removeFile(file);
1941 for (final FileBody body : file.getBodies())
1942 filesToRemove.add(body.getStoredFilePath());
1944 touchParentFolders(parent, user, new Date());
1946 //then remove physical files if everything is ok
1947 for(String physicalFileName : filesToRemove)
1948 deleteActualFile(physicalFileName);
1949 //then unindex deleted files
1950 for(Long fileId : fileIds)
1951 indexFile(fileId, true);
1956 public void moveFilesToTrash(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1957 for(Long l : fileIds)
1958 moveFileToTrash(userId, l);
1963 public void removeFilesFromTrash(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1964 for(Long l : fileIds)
1965 removeFileFromTrash(userId, l);
1970 public Nonce createNonce(Long userId) throws ObjectNotFoundException {
1972 throw new ObjectNotFoundException("No user specified");
1973 User user = dao.getEntityById(User.class, userId);
1974 Nonce nonce = Nonce.createNonce(user.getId());
1980 public Nonce getNonce(String nonce, Long userId) throws ObjectNotFoundException {
1982 throw new ObjectNotFoundException("No user specified");
1984 throw new ObjectNotFoundException("No nonce specified");
1985 return dao.getNonce(nonce, userId);
1989 public void removeNonce(Long id) throws ObjectNotFoundException {
1991 throw new ObjectNotFoundException("No nonce specified");
1992 Nonce nonce = dao.getEntityById(Nonce.class, id);
1997 public void activateUserNonce(Long userId, String nonce, Date nonceExpiryDate) throws ObjectNotFoundException {
1999 throw new ObjectNotFoundException("No user specified");
2000 User user = dao.getEntityById(User.class, userId);
2001 user.setNonce(nonce);
2002 user.setNonceExpiryDate(nonceExpiryDate);
2006 public StatsDTO getUserStatistics(Long userId) throws ObjectNotFoundException {
2008 throw new ObjectNotFoundException("No user specified");
2009 StatsDTO stats = new StatsDTO();
2010 stats.setFileCount(dao.getFileCount(userId));
2011 Long fileSize = dao.getFileSize(userId);
2012 stats.setFileSize(fileSize);
2013 Long quota = getQuota(userId);
2014 Long quotaLeft = quota - fileSize;
2015 stats.setQuotaLeftSize(quotaLeft);
2020 public List<FileBodyDTO> getVersions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
2022 throw new ObjectNotFoundException("No user specified");
2024 throw new ObjectNotFoundException("No file specified");
2025 User user = dao.getEntityById(User.class, userId);
2026 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
2027 if(!header.hasReadPermission(user))
2028 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2029 List<FileBodyDTO> result = new LinkedList<FileBodyDTO>();
2030 for(int i = header.getBodies().size()-1 ; i>=0; i--)
2031 result.add(header.getBodies().get(i).getDTO());
2036 public void removeVersion(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
2038 throw new ObjectNotFoundException("No user specified");
2040 throw new ObjectNotFoundException("No file specified");
2042 throw new ObjectNotFoundException("No body specified");
2043 User user = dao.getEntityById(User.class, userId);
2044 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
2045 if(!header.hasWritePermission(user))
2046 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2047 FileBody body = dao.getEntityById(FileBody.class, bodyId);
2048 if(body.equals(header.getCurrentBody())){
2050 if(header.getBodies().size() == 1)
2051 throw new InsufficientPermissionsException("You cant delete this version, Delete file instead!");
2052 for(FileBody b : header.getBodies())
2053 if(b.getVersion() == body.getVersion()-1)
2054 header.setCurrentBody(b);
2056 deleteActualFile(body.getStoredFilePath());
2057 header.getBodies().remove(body);
2059 Folder parent = header.getFolder();
2060 touchParentFolders(parent, user, new Date());
2065 public void restoreVersion(Long userId, Long fileId, int version) throws ObjectNotFoundException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
2067 throw new ObjectNotFoundException("No user specified");
2069 throw new ObjectNotFoundException("No file specified");
2070 User user = dao.getEntityById(User.class, userId);
2071 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
2072 if(!header.hasWritePermission(user))
2073 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2074 FileBody body = dao.getFileVersion(fileId, version);
2075 final File fileContents = new File(body.getStoredFilePath());
2078 updateFileContents(userId, fileId, body.getMimeType(), new FileInputStream(fileContents) );
2079 } catch (FileNotFoundException e) {
2080 throw new GSSIOException(e);
2086 * @see gr.ebs.gss.server.ejb.ExternalAPI#removeOldVersions(java.lang.Long, java.lang.Long)
2089 public void removeOldVersions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
2091 throw new ObjectNotFoundException("No user specified");
2093 throw new ObjectNotFoundException("No file specified");
2094 User user = dao.getEntityById(User.class, userId);
2095 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
2096 if(!header.hasWritePermission(user))
2097 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2098 Iterator<FileBody> it = header.getBodies().iterator();
2099 while(it.hasNext()){
2100 FileBody body = it.next();
2101 if(!body.equals(header.getCurrentBody())){
2102 deleteActualFile(body.getStoredFilePath());
2107 header.getCurrentBody().setVersion(1);
2109 Folder parent = header.getFolder();
2110 touchParentFolders(parent, user, new Date());
2114 * Gets the quota left for specified user ID.
2116 private Long getQuotaLeft(Long userId) throws ObjectNotFoundException{
2117 Long fileSize = dao.getFileSize(userId);
2118 Long quota = getQuota(userId);
2119 return quota - fileSize;
2123 * Gets the quota for specified user ID.
2125 private Long getQuota(Long userId) throws ObjectNotFoundException{
2126 UserClass uc = getUser(userId).getUserClass();
2128 uc = getDefaultUserClass();
2129 return uc.getQuota();
2133 public void rebuildSolrIndex() {
2134 MessageProducer sender = null;
2135 Session session = null;
2136 Connection qConn = null;
2138 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
2139 DocumentBuilder db = dbf.newDocumentBuilder();
2140 Document doc = db.newDocument();
2141 Node root = doc.createElement("delete");
2142 doc.appendChild(root);
2143 Node queryNode = doc.createElement("query");
2144 root.appendChild(queryNode);
2145 queryNode.appendChild(doc.createTextNode("*:*"));
2147 TransformerFactory fact = TransformerFactory.newInstance();
2148 Transformer trans = fact.newTransformer();
2149 trans.setOutputProperty(OutputKeys.INDENT, "yes");
2150 StringWriter sw = new StringWriter();
2151 StreamResult sr = new StreamResult(sw);
2152 DOMSource source = new DOMSource(doc);
2153 trans.transform(source, sr);
2154 logger.debug(sw.toString());
2156 HttpClient httpClient = new HttpClient();
2157 PostMethod method = new PostMethod(getConfiguration().getString("solrUpdateUrl"));
2158 method.setRequestEntity(new StringRequestEntity(sw.toString()));
2161 String response = null;
2163 statusCode = httpClient.executeMethod(method);
2164 logger.debug("HTTP status: " + statusCode);
2165 response = method.getResponseBodyAsString();
2166 logger.debug(response);
2168 if (statusCode != 200 && retryCount < 3)
2170 Thread.sleep(10000); //Give Solr a little time to be available
2171 } catch (InterruptedException e) {
2173 } while (statusCode != 200 && retryCount < 3);
2174 method.releaseConnection();
2175 if (statusCode != 200)
2176 throw new EJBException("Cannot clear Solr index. Solr response is:\n" + response);
2177 List<Long> fileIds = dao.getAllFileIds();
2179 Context jndiCtx = new InitialContext();
2180 ConnectionFactory factory = (QueueConnectionFactory) jndiCtx.lookup("java:/JmsXA");
2181 Queue queue = (Queue) jndiCtx.lookup("queue/gss-indexingQueue");
2182 qConn = factory.createConnection();
2183 session = qConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
2184 sender = session.createProducer(queue);
2186 for (Long id : fileIds) {
2187 MapMessage map = session.createMapMessage();
2188 map.setObject("id", id);
2189 map.setBoolean("delete", false);
2192 sendOptimize(httpClient, 0);
2193 } catch (DOMException e) {
2194 throw new EJBException(e);
2195 } catch (TransformerConfigurationException e) {
2196 throw new EJBException(e);
2197 } catch (IllegalArgumentException e) {
2198 throw new EJBException(e);
2199 } catch (HttpException e) {
2200 throw new EJBException(e);
2201 } catch (UnsupportedEncodingException e) {
2202 throw new EJBException(e);
2203 } catch (ParserConfigurationException e) {
2204 throw new EJBException(e);
2205 } catch (TransformerException e) {
2206 throw new EJBException(e);
2207 } catch (IOException e) {
2208 throw new EJBException(e);
2209 } catch (NamingException e) {
2210 throw new EJBException(e);
2211 } catch (JMSException e) {
2212 throw new EJBException(e);
2218 if (session != null)
2223 catch (JMSException e) {
2230 * Sends a optimize message to the solr server
2233 * @param retryCount If the commit fails, it is retried three times. This parameter is passed in the recursive
2234 * calls to stop the recursion
2235 * @throws UnsupportedEncodingException
2236 * @throws IOException
2237 * @throws HttpException
2239 private void sendOptimize(HttpClient httpClient, int retryCount) throws UnsupportedEncodingException, IOException, HttpException {
2240 PostMethod method = null;
2242 logger.debug("Optimize retry: " + retryCount);
2243 method = new PostMethod(getConfiguration().getString("solrUpdateUrl"));
2244 method.setRequestEntity(new StringRequestEntity("<optimize/>", "text/xml", "iso8859-1"));
2245 int statusCode = httpClient.executeMethod(method);
2246 logger.debug("HTTP status: " + statusCode);
2247 String response = method.getResponseBodyAsString();
2248 logger.debug(response);
2249 if (statusCode != 200 && retryCount < 2) {
2251 Thread.sleep(10000); //Give Solr a little time to be available
2252 } catch (InterruptedException e) {
2254 sendOptimize(httpClient, retryCount + 1);
2259 method.releaseConnection();
2264 public FileHeaderDTO createFile(Long userId, Long folderId, String name, String mimeType, long fileSize, String filePath)
2265 throws DuplicateNameException, ObjectNotFoundException, GSSIOException,
2266 InsufficientPermissionsException, QuotaExceededException {
2269 throw new ObjectNotFoundException("No user specified");
2270 if (folderId == null)
2271 throw new ObjectNotFoundException("No folder specified");
2272 String contentType = mimeType;
2273 if (StringUtils.isEmpty(mimeType))
2274 contentType = DEFAULT_MIME_TYPE;
2275 if (StringUtils.isEmpty(name))
2276 throw new ObjectNotFoundException("No file name specified");
2277 if (dao.existsFolderOrFile(folderId, name))
2278 throw new DuplicateNameException("A folder or file with the name '" + name +
2279 "' already exists at this level");
2281 // Do the actual work.
2282 Folder parent = null;
2284 parent = dao.getEntityById(Folder.class, folderId);
2285 } catch (final ObjectNotFoundException onfe) {
2286 // Supply a more accurate problem description.
2287 throw new ObjectNotFoundException("Parent folder not found");
2289 final User owner = dao.getEntityById(User.class, userId);
2290 if (!parent.hasWritePermission(owner))
2291 throw new InsufficientPermissionsException("You don't have the permissions to write to this folder");
2292 final FileHeader file = new FileHeader();
2294 parent.addFile(file);
2295 // set file owner to folder owner
2296 file.setOwner(parent.getOwner());
2297 //set file's readForAll value according to parent folder readForAll value
2298 file.setReadForAll(parent.isReadForAll());
2300 final Date now = new Date();
2301 final AuditInfo auditInfo = new AuditInfo();
2302 auditInfo.setCreatedBy(owner);
2303 auditInfo.setCreationDate(now);
2304 auditInfo.setModifiedBy(owner);
2305 auditInfo.setModificationDate(now);
2306 file.setAuditInfo(auditInfo);
2307 // TODO set the proper versioning flag on creation
2308 file.setVersioned(false);
2310 for (final Permission p : parent.getPermissions()) {
2311 final Permission permission = new Permission();
2312 permission.setGroup(p.getGroup());
2313 permission.setUser(p.getUser());
2314 permission.setRead(p.getRead());
2315 permission.setWrite(p.getWrite());
2316 permission.setModifyACL(p.getModifyACL());
2317 file.addPermission(permission);
2320 // Create the file body.
2322 createFileBody(name, contentType, fileSize, filePath, file, auditInfo);
2323 } catch (FileNotFoundException e) {
2324 throw new GSSIOException(e);
2326 touchParentFolders(parent, owner, new Date());
2328 indexFile(file.getId(), false);
2330 return file.getDTO();
2334 public FileHeaderDTO updateFileContents(Long userId, Long fileId, String mimeType, long fileSize, String filePath) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
2336 throw new ObjectNotFoundException("No user specified");
2338 throw new ObjectNotFoundException("No file specified");
2339 String contentType = mimeType;
2341 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
2343 // if no mime type or the generic mime type is defined by the client, then try to identify it from the filename extension
2344 if (StringUtils.isEmpty(mimeType) || "application/octet-stream".equals(mimeType)
2345 || "application/download".equals(mimeType) || "application/force-download".equals(mimeType)
2346 || "octet/stream".equals(mimeType) || "application/unknown".equals(mimeType))
2347 contentType = identifyMimeType(file.getName());
2349 final User owner = dao.getEntityById(User.class, userId);
2350 if (!file.hasWritePermission(owner))
2351 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2352 final Date now = new Date();
2353 final AuditInfo auditInfo = new AuditInfo();
2354 auditInfo.setCreatedBy(owner);
2355 auditInfo.setCreationDate(now);
2356 auditInfo.setModifiedBy(owner);
2357 auditInfo.setModificationDate(now);
2359 createFileBody(file.getName(), contentType, fileSize, filePath, file, auditInfo);
2360 } catch (FileNotFoundException e) {
2361 throw new GSSIOException(e);
2363 Folder parent = file.getFolder();
2364 touchParentFolders(parent, owner, new Date());
2366 indexFile(fileId, false);
2367 return file.getDTO();
2371 * Helper method for identifying mime type by examining the filename extension
2374 * @return the mime type
2376 private String identifyMimeType(String filename) {
2377 if (filename.indexOf('.') != -1) {
2378 String extension = filename.substring(filename.lastIndexOf('.')).toLowerCase(Locale.ENGLISH);
2379 if (".doc".equals(extension))
2380 return "application/msword";
2381 else if (".xls".equals(extension))
2382 return "application/vnd.ms-excel";
2383 else if (".ppt".equals(extension))
2384 return "application/vnd.ms-powerpoint";
2385 else if (".pdf".equals(extension))
2386 return "application/pdf";
2387 else if (".gif".equals(extension))
2389 else if (".jpg".equals(extension) || ".jpeg".equals(extension) || ".jpe".equals(extension))
2390 return "image/jpeg";
2391 else if (".tiff".equals(extension) || ".tif".equals(extension))
2392 return "image/tiff";
2393 else if (".png".equals(extension))
2395 else if (".bmp".equals(extension))
2398 // when all else fails assign the default mime type
2399 return DEFAULT_MIME_TYPE;
2403 * Helper method to create a new file body and attach it as the current body
2404 * of the provided file header.
2406 * @param name the original file name
2407 * @param mimeType the content type
2408 * @param fileSize the uploaded file size
2409 * @param filePath the uploaded file full path
2410 * @param header the file header that will be associated with the new body
2411 * @param auditInfo the audit info
2412 * @param owner the owner of the file
2413 * @throws FileNotFoundException
2414 * @throws QuotaExceededException
2415 * @throws ObjectNotFoundException if the owner was not found
2417 private void createFileBody(String name, String mimeType, long fileSize, String filePath,
2418 FileHeader header, AuditInfo auditInfo)
2419 throws FileNotFoundException, QuotaExceededException, ObjectNotFoundException {
2421 long currentTotalSize = 0;
2422 if (!header.isVersioned() && header.getCurrentBody() != null && header.getBodies() != null)
2423 currentTotalSize = header.getTotalSize();
2424 Long quotaLeft = getQuotaLeft(header.getOwner().getId());
2425 if(quotaLeft < fileSize-currentTotalSize) {
2426 // quota exceeded -> delete the file
2427 deleteActualFile(filePath);
2428 throw new QuotaExceededException("Not enough free space available");
2431 FileBody body = new FileBody();
2433 // if no mime type or the generic mime type is defined by the client, then try to identify it from the filename extension
2434 if (StringUtils.isEmpty(mimeType) || "application/octet-stream".equals(mimeType)
2435 || "application/download".equals(mimeType) || "application/force-download".equals(mimeType)
2436 || "octet/stream".equals(mimeType) || "application/unknown".equals(mimeType))
2437 body.setMimeType(identifyMimeType(name));
2439 body.setMimeType(mimeType);
2440 body.setAuditInfo(auditInfo);
2441 body.setFileSize(fileSize);
2442 body.setOriginalFilename(name);
2443 body.setStoredFilePath(filePath);
2444 //CLEAR OLD VERSION IF FILE IS NOT VERSIONED AND GETS UPDATED
2445 if(!header.isVersioned() && header.getCurrentBody() != null){
2446 header.setCurrentBody(null);
2447 if (header.getBodies() != null) {
2448 Iterator<FileBody> it = header.getBodies().iterator();
2449 while(it.hasNext()){
2450 FileBody bo = it.next();
2451 deleteActualFile(bo.getStoredFilePath());
2459 header.addBody(body);
2460 header.setAuditInfo(auditInfo);
2467 @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
2468 public File uploadFile(InputStream stream, Long userId) throws IOException, ObjectNotFoundException {
2470 throw new ObjectNotFoundException("No user specified");
2471 User owner = dao.getEntityById(User.class, userId);
2473 throw new ObjectNotFoundException("No user specified");
2474 long start = 0, end = 0;
2475 if (logger.isDebugEnabled())
2476 start = System.currentTimeMillis();
2477 File result = new File(generateRepositoryFilePath());
2479 final FileOutputStream output = new FileOutputStream(result);
2480 final byte[] buffer = new byte[UPLOAD_BUFFER_SIZE];
2483 while (-1 != (n = stream.read(buffer)))
2484 output.write(buffer, 0, n);
2487 } catch (IOException e) {
2488 if (!result.delete())
2489 logger.warn("Could not delete " + result.getPath());
2492 if (logger.isDebugEnabled()) {
2493 end = System.currentTimeMillis();
2494 logger.debug("Time to upload: " + (end - start) + " (msec)");
2501 public void createFileUploadProgress(Long userId, String filename, Long bytesTransfered, Long fileSize) throws ObjectNotFoundException{
2504 throw new ObjectNotFoundException("No user specified");
2505 User user = dao.getEntityById(User.class, userId);
2506 FileUploadStatus status = dao.getFileUploadStatus(userId, filename);
2508 status = new FileUploadStatus();
2509 status.setOwner(user);
2510 status.setFilename(filename);
2511 status.setBytesUploaded(bytesTransfered);
2512 status.setFileSize(fileSize);
2516 status.setBytesUploaded(bytesTransfered);
2517 status.setFileSize(fileSize);
2524 public void removeFileUploadProgress(Long userId, String filename) throws ObjectNotFoundException{
2526 throw new ObjectNotFoundException("No user specified");
2527 FileUploadStatus status = dao.getFileUploadStatus(userId, filename);
2533 public FileUploadStatus getFileUploadStatus(Long userId, String fileName) {
2534 return dao.getFileUploadStatus(userId, fileName);
2538 public FolderDTO getFolderWithSubfolders(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
2540 throw new ObjectNotFoundException("No user specified");
2541 if (folderId == null)
2542 throw new ObjectNotFoundException("No folder specified");
2543 final User user = dao.getEntityById(User.class, userId);
2544 final Folder folder = dao.getEntityById(Folder.class, folderId);
2545 // Check permissions
2546 if (!folder.hasReadPermission(user))
2547 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
2548 List<FolderDTO> subfolders = new ArrayList<FolderDTO>();
2549 if (folder.hasReadPermission(user))
2550 for (Folder f : folder.getSubfolders())
2551 if (f.hasReadPermission(user) && !f.isDeleted())
2552 subfolders.add(f.getDTO());
2553 FolderDTO result = folder.getDTO();
2554 result.setSubfolders(subfolders);
2555 return folder.getDTO();
2559 public FolderDTO getFolderWithSubfolders(Long userId, Long callingUserId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
2561 throw new ObjectNotFoundException("No user specified");
2562 if (folderId == null)
2563 throw new ObjectNotFoundException("No folder specified");
2564 User user = dao.getEntityById(User.class, callingUserId);
2565 Folder folder = dao.getEntityById(Folder.class, folderId);
2566 // Check permissions
2567 if (!folder.hasReadPermission(user))
2568 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
2570 FolderDTO result = folder.getDTO();
2571 result.setSubfolders(getSharedSubfolders(userId, callingUserId, folder.getId()));
2576 public FileBodyDTO getFileVersion(Long userId, Long fileId, int version)
2577 throws ObjectNotFoundException, InsufficientPermissionsException {
2579 throw new ObjectNotFoundException("No user specified");
2581 throw new ObjectNotFoundException("No file specified");
2583 throw new ObjectNotFoundException("No valid version specified");
2584 User user = dao.getEntityById(User.class, userId);
2585 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
2586 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
2587 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2588 FileBody body = dao.getFileVersion(fileId, version);
2589 return body.getDTO();
2593 public User updateUserPolicyAcceptance(Long userId, boolean isAccepted) throws ObjectNotFoundException {
2595 throw new ObjectNotFoundException("No user specified");
2596 User user = dao.getEntityById(User.class, userId);
2597 user.setAcceptedPolicy(isAccepted);
2602 public void updateAccounting(User user, Date date, long bandwidthDiff) {
2603 dao.updateAccounting(user, date, bandwidthDiff);
2607 public boolean canReadFolder(Long userId, Long folderId) throws ObjectNotFoundException {
2609 throw new ObjectNotFoundException("No user specified");
2610 if (folderId == null)
2611 throw new ObjectNotFoundException("No folder specified");
2612 User user = dao.getEntityById(User.class, userId);
2613 Folder folder = dao.getEntityById(Folder.class, folderId);
2614 // Check permissions
2615 if (!folder.hasReadPermission(user))
2621 public String resetWebDAVPassword(Long userId) throws ObjectNotFoundException {
2623 throw new ObjectNotFoundException("No user specified");
2624 User user = dao.getEntityById(User.class, userId);
2625 user.generateWebDAVPassword();
2626 return user.getWebDAVPassword();
2630 public Invitation findInvite(String code) {
2633 return dao.findInvite(code);
2637 public void createLdapUser(String username, String firstname, String lastname, String email, String password) {
2638 LDAPConnection lc = new LDAPConnection();
2639 LDAPAttributeSet attributeSet = new LDAPAttributeSet();
2640 attributeSet.add(new LDAPAttribute("objectClass", getConfiguration().getStringArray("objectClass")));
2641 attributeSet.add(new LDAPAttribute("uid", username));
2642 attributeSet.add(new LDAPAttribute("cn", new String[]{firstname + " " + lastname}));
2643 attributeSet.add(new LDAPAttribute("sn", lastname));
2644 attributeSet.add(new LDAPAttribute("givenName", firstname));
2645 attributeSet.add(new LDAPAttribute("mail", email));
2646 attributeSet.add(new LDAPAttribute("userPassword", password));
2647 String dn = "uid=" + username + "," + getConfiguration().getString("baseDn");
2648 LDAPEntry newEntry = new LDAPEntry(dn, attributeSet);
2650 lc.connect(getConfiguration().getString("ldapHost"), LDAPConnection.DEFAULT_PORT);
2651 lc.bind(LDAPConnection.LDAP_V3, getConfiguration().getString("bindDn"),
2652 getConfiguration().getString("bindPassword").getBytes("UTF8"));
2654 logger.info("Successfully added LDAP account: " + dn);
2656 } catch(LDAPException e) {
2657 throw new RuntimeException(e);
2658 } catch(UnsupportedEncodingException e) {
2659 throw new RuntimeException(e);
2665 public UserClass upgradeUserClass(String username, String code) throws ObjectNotFoundException, InvitationUsedException {
2666 User user = findUser(username);
2668 throw new ObjectNotFoundException("The user was not found");
2669 Invitation invite = findInvite(code);
2670 if (invite.getUser() != null)
2671 throw new InvitationUsedException("This code has already been used");
2672 invite.setUser(user);
2673 UserClass couponClass = getCouponUserClass();
2674 user.setUserClass(couponClass);
2679 public UserClass getCouponUserClass() {
2680 return dao.findCouponUserClass();
2684 * Mark the folder as modified from the specified user and change it's modification date.
2686 private void touchFolder(Folder f, User _user, Date now){
2687 final AuditInfo auditInfo = f.getAuditInfo();
2688 auditInfo.setModificationDate(now);
2689 auditInfo.setModifiedBy(_user);
2690 f.setAuditInfo(auditInfo);
2694 * Mark the file as modified from the specified user and change it's modification date.
2696 private void touchFile(FileHeader f, User _user, Date now){
2697 final AuditInfo auditInfo = f.getAuditInfo();
2698 auditInfo.setModificationDate(now);
2699 auditInfo.setModifiedBy(_user);
2700 f.setAuditInfo(auditInfo);
2704 * Set the provided readForAll as the new readforAll value of the specified
2705 * folder and sub-folders.
2710 * @throws ObjectNotFoundException
2713 private void setFolderReadForAll(User user, Folder folder, Boolean readForAll){
2714 if (readForAll != null && user.equals(folder.getOwner())){
2715 folder.setReadForAll(readForAll);
2717 for (FileHeader file : folder.getFiles())
2718 file.setReadForAll(readForAll);
2720 //only update subfolders when readforall is true. otherwise all sub-folders stay untouched
2721 for (Folder sub : folder.getSubfolders())
2722 setFolderReadForAll(user, sub, readForAll);
2729 * Update the userLogin with the values from the supplied object.
2732 public void addUserLogin(UserLogin userLogin) {
2733 dao.update(userLogin);
2738 * Retrieves the current session user login and the user's last login
2741 * @return a list of last two user logins
2742 * @throws ObjectNotFoundException
2745 public List<UserLogin> getUserLogins(Long userId) throws ObjectNotFoundException{
2746 List<UserLogin> userLoginResults = new ArrayList<UserLogin>();
2747 userLoginResults = dao.getLoginsForUser(userId);
2748 if(userLoginResults.size() == 0)
2749 throw new ObjectNotFoundException("No userlogin found for the user");
2750 //if the user logins for the first time lastLoginDate = currentLoginDate
2751 if(userLoginResults.size()==1)
2752 userLoginResults.add(userLoginResults.get(0));
2753 return userLoginResults;