2 * Copyright 2007, 2008, 2009 Electronic Business Systems Ltd.
4 * This file is part of GSS.
6 * GSS is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GSS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GSS. If not, see <http://www.gnu.org/licenses/>.
19 package gr.ebs.gss.server.ejb;
21 import static gr.ebs.gss.server.configuration.GSSConfigurationFactory.getConfiguration;
22 import gr.ebs.gss.client.exceptions.DuplicateNameException;
23 import gr.ebs.gss.client.exceptions.GSSIOException;
24 import gr.ebs.gss.client.exceptions.InsufficientPermissionsException;
25 import gr.ebs.gss.client.exceptions.ObjectNotFoundException;
26 import gr.ebs.gss.client.exceptions.QuotaExceededException;
27 import gr.ebs.gss.server.domain.AuditInfo;
28 import gr.ebs.gss.server.domain.FileBody;
29 import gr.ebs.gss.server.domain.FileHeader;
30 import gr.ebs.gss.server.domain.FileTag;
31 import gr.ebs.gss.server.domain.FileUploadStatus;
32 import gr.ebs.gss.server.domain.Folder;
33 import gr.ebs.gss.server.domain.Group;
34 import gr.ebs.gss.server.domain.Nonce;
35 import gr.ebs.gss.server.domain.Permission;
36 import gr.ebs.gss.server.domain.User;
37 import gr.ebs.gss.server.domain.dto.FileBodyDTO;
38 import gr.ebs.gss.server.domain.dto.FileHeaderDTO;
39 import gr.ebs.gss.server.domain.dto.FolderDTO;
40 import gr.ebs.gss.server.domain.dto.GroupDTO;
41 import gr.ebs.gss.server.domain.dto.PermissionDTO;
42 import gr.ebs.gss.server.domain.dto.StatsDTO;
43 import gr.ebs.gss.server.domain.dto.UserDTO;
46 import java.io.FileInputStream;
47 import java.io.FileNotFoundException;
48 import java.io.FileOutputStream;
49 import java.io.IOException;
50 import java.io.InputStream;
51 import java.io.StringWriter;
52 import java.io.UnsupportedEncodingException;
53 import java.util.ArrayList;
54 import java.util.Date;
55 import java.util.Iterator;
56 import java.util.LinkedHashSet;
57 import java.util.LinkedList;
58 import java.util.List;
59 import java.util.Locale;
60 import java.util.Random;
62 import java.util.StringTokenizer;
65 import javax.ejb.EJBException;
66 import javax.ejb.Stateless;
67 import javax.ejb.TransactionAttribute;
68 import javax.ejb.TransactionAttributeType;
69 import javax.jms.Connection;
70 import javax.jms.ConnectionFactory;
71 import javax.jms.JMSException;
72 import javax.jms.MapMessage;
73 import javax.jms.MessageProducer;
74 import javax.jms.Queue;
75 import javax.jms.QueueConnectionFactory;
76 import javax.jms.Session;
77 import javax.jws.WebMethod;
78 import javax.naming.Context;
79 import javax.naming.InitialContext;
80 import javax.naming.NamingException;
81 import javax.xml.parsers.DocumentBuilder;
82 import javax.xml.parsers.DocumentBuilderFactory;
83 import javax.xml.parsers.ParserConfigurationException;
84 import javax.xml.transform.OutputKeys;
85 import javax.xml.transform.Transformer;
86 import javax.xml.transform.TransformerConfigurationException;
87 import javax.xml.transform.TransformerException;
88 import javax.xml.transform.TransformerFactory;
89 import javax.xml.transform.dom.DOMSource;
90 import javax.xml.transform.stream.StreamResult;
92 import org.apache.commons.httpclient.HttpClient;
93 import org.apache.commons.httpclient.HttpException;
94 import org.apache.commons.httpclient.NameValuePair;
95 import org.apache.commons.httpclient.methods.GetMethod;
96 import org.apache.commons.httpclient.methods.PostMethod;
97 import org.apache.commons.httpclient.methods.StringRequestEntity;
98 import org.apache.commons.lang.StringUtils;
99 import org.apache.commons.logging.Log;
100 import org.apache.commons.logging.LogFactory;
101 import org.w3c.dom.DOMException;
102 import org.w3c.dom.Document;
103 import org.w3c.dom.Node;
104 import org.w3c.dom.NodeList;
105 import org.xml.sax.SAXException;
108 * The concrete implementation of the ExternalAPI interface.
113 public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
115 * The default MIME type for files without an explicit one.
117 private static final String DEFAULT_MIME_TYPE = "application/octet-stream";
120 * The size of the buffer that is used to temporarily store chunks of
121 * uploaded files, while storing them to the file repository.
123 private static final int UPLOAD_BUFFER_SIZE = 1024 * 4;
128 private static Log logger = LogFactory.getLog(ExternalAPIBean.class);
131 * Injected reference to the GSSDAO data access facade.
138 * A cached random number generator for creating unique filenames.
140 private static Random random = new Random();
143 public FolderDTO getRootFolder(Long userId) throws ObjectNotFoundException {
145 throw new ObjectNotFoundException("No user specified");
146 Folder folder = dao.getRootFolder(userId);
147 return folder.getDTO();
153 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFolder(java.lang.Long)
155 public FolderDTO getFolder(final Long userId, final Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
157 throw new ObjectNotFoundException("No user specified");
158 if (folderId == null)
159 throw new ObjectNotFoundException("No folder specified");
160 final User user = dao.getEntityById(User.class, userId);
161 final Folder folder = dao.getEntityById(Folder.class, folderId);
163 if (!folder.hasReadPermission(user))
164 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
165 return folder.getDTO();
169 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUser(java.lang.Long)
171 public User getUser(Long userId) throws ObjectNotFoundException {
173 throw new ObjectNotFoundException("No user specified");
174 return dao.getEntityById(User.class, userId);
178 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUserDTO(java.lang.Long)
180 public UserDTO getUserDTO(final Long userId) throws ObjectNotFoundException {
181 return getUser(userId).getDTO();
187 * @see gr.ebs.gss.server.ejb.ExternalAPI#getGroup(java.lang.Long)
189 public GroupDTO getGroup(final Long groupId) throws ObjectNotFoundException {
191 throw new ObjectNotFoundException("No group specified");
192 final Group group = dao.getEntityById(Group.class, groupId);
193 return group.getDTO();
197 public GroupDTO getGroup(Long userId, String name) throws ObjectNotFoundException {
199 throw new ObjectNotFoundException("No user specified");
201 throw new ObjectNotFoundException("No group specified");
202 User user = dao.getEntityById(User.class, userId);
203 List<Group> groups = user.getGroupsSpecified();
204 for (Group group: groups)
205 if (group.getName().equals(name))
206 return group.getDTO();
207 throw new ObjectNotFoundException("Group " + name + " not found");
213 * @see gr.ebs.gss.server.ejb.ExternalAPI#getGroups(java.lang.Long)
215 public List<GroupDTO> getGroups(final Long userId) throws ObjectNotFoundException {
217 throw new ObjectNotFoundException("No user specified");
218 final List<Group> groups = dao.getGroups(userId);
219 final List<GroupDTO> result = new ArrayList<GroupDTO>();
220 for (final Group g : groups)
221 result.add(g.getDTO());
226 public List<FileHeaderDTO> getFiles(Long userId, Long folderId, boolean ignoreDeleted)
227 throws ObjectNotFoundException, InsufficientPermissionsException {
230 throw new ObjectNotFoundException("No user specified");
231 if (folderId == null)
232 throw new ObjectNotFoundException("No folder specified");
233 User user = dao.getEntityById(User.class, userId);
234 Folder folder = dao.getEntityById(Folder.class, folderId);
235 if (!folder.hasReadPermission(user))
236 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
237 // Do the actual work.
238 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
239 List<FileHeader> files = dao.getFiles(folderId, userId, ignoreDeleted);
240 for (FileHeader f : files)
241 result.add(f.getDTO());
248 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsers(java.lang.Long,
251 public List<UserDTO> getUsers(final Long userId, final Long groupId) throws ObjectNotFoundException {
254 throw new ObjectNotFoundException("No user specified");
256 throw new ObjectNotFoundException("No group specified");
258 // Do the actual work.
259 final List<User> users = dao.getUsers(groupId);
260 final List<UserDTO> result = new ArrayList<UserDTO>();
261 for (final User u : users)
262 result.add(u.getDTO());
267 public FolderDTO createFolder(Long userId, Long parentId, String name)
268 throws DuplicateNameException, ObjectNotFoundException, InsufficientPermissionsException {
271 throw new ObjectNotFoundException("No user specified");
272 if (StringUtils.isEmpty(name))
273 throw new ObjectNotFoundException("New folder name is empty");
274 if (parentId == null)
275 throw new ObjectNotFoundException("No parent specified");
276 if (dao.existsFolderOrFile(parentId, name))
277 throw new DuplicateNameException("A folder or file with the name '" +
278 name + "' already exists at this level");
280 User creator = dao.getEntityById(User.class, userId);
282 Folder parent = null;
284 parent = dao.getEntityById(Folder.class, parentId);
285 } catch (ObjectNotFoundException onfe) {
286 // Supply a more accurate problem description.
287 throw new ObjectNotFoundException("Parent folder not found");
289 if (!parent.hasWritePermission(creator))
290 throw new InsufficientPermissionsException("You don't have the permissions" +
291 " to write to this folder");
293 // Do the actual work.
294 return createFolder(name, parent, creator);
298 * Create a new folder with the provided name, parent and owner.
303 * @return the new folder
305 private FolderDTO createFolder(String name, Folder parent, User creator) {
306 Folder folder = new Folder();
307 folder.setName(name);
308 if (parent != null) {
309 parent.addSubfolder(folder);
310 folder.setOwner(parent.getOwner());
312 folder.setOwner(creator);
314 Date now = new Date();
315 AuditInfo auditInfo = new AuditInfo();
316 auditInfo.setCreatedBy(creator);
317 auditInfo.setCreationDate(now);
318 auditInfo.setModifiedBy(creator);
319 auditInfo.setModificationDate(now);
320 folder.setAuditInfo(auditInfo);
323 for (Permission p : parent.getPermissions()) {
324 Permission permission = new Permission();
325 permission.setGroup(p.getGroup());
326 permission.setUser(p.getUser());
327 permission.setRead(p.getRead());
328 permission.setWrite(p.getWrite());
329 permission.setModifyACL(p.getModifyACL());
330 folder.addPermission(permission);
333 Permission permission = new Permission();
334 permission.setUser(creator);
335 permission.setRead(true);
336 permission.setWrite(true);
337 permission.setModifyACL(true);
338 folder.addPermission(permission);
341 return folder.getDTO();
345 * Deletes the given folder and all its subfolders and files
346 * Only the permissions for top folder are checked
348 * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteFolder(java.lang.Long,
351 public void deleteFolder(final Long userId, final Long folderId) throws InsufficientPermissionsException, ObjectNotFoundException {
354 throw new ObjectNotFoundException("No user specified");
355 if (folderId == null)
356 throw new ObjectNotFoundException("No folder specified");
358 // Do the actual work.
359 final Folder folder = dao.getEntityById(Folder.class, folderId);
360 final Folder parent = folder.getParent();
362 throw new ObjectNotFoundException("Deleting the root folder is not allowed");
363 final User user = dao.getEntityById(User.class, userId);
364 if (!folder.hasDeletePermission(user)) {
365 logger.info("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
366 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
368 removeSubfolderFiles(folder);
369 parent.removeSubfolder(folder);
374 * Traverses the folder and deletes all actual files (file system)
375 * regardless of permissions
379 private void removeSubfolderFiles(Folder folder) {
380 //remove files for all subfolders
381 for (Folder subfolder:folder.getSubfolders())
382 removeSubfolderFiles(subfolder);
383 //remove this folder's file bodies (actual files)
384 for (FileHeader file:folder.getFiles()) {
385 for (FileBody body:file.getBodies())
386 deleteActualFile(body.getStoredFilePath());
387 indexFile(file.getId(), true);
391 @SuppressWarnings("unchecked")
392 public List<FolderDTO> getSubfolders(Long userId, Long folderId)
393 throws ObjectNotFoundException, InsufficientPermissionsException {
395 throw new ObjectNotFoundException("No user specified");
396 if (folderId == null)
397 throw new ObjectNotFoundException("No folder specified");
398 User user = dao.getEntityById(User.class, userId);
399 Folder folder = dao.getEntityById(Folder.class, folderId);
400 if (!folder.hasReadPermission(user))
401 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
402 List<FolderDTO> result = new ArrayList<FolderDTO>();
403 if (folder.hasReadPermission(user))
404 for (Folder f : folder.getSubfolders())
405 if (f.hasReadPermission(user) && !f.isDeleted())
406 result.add(f.getDTO());
411 public FolderDTO modifyFolder(Long userId, Long folderId, String folderName)
412 throws InsufficientPermissionsException, ObjectNotFoundException, DuplicateNameException {
416 throw new ObjectNotFoundException("No user specified");
417 if (folderId == null)
418 throw new ObjectNotFoundException("No folder specified");
419 if (StringUtils.isEmpty(folderName))
420 throw new ObjectNotFoundException("New folder name is empty");
422 Folder folder = dao.getEntityById(Folder.class, folderId);
423 User user = dao.getEntityById(User.class, userId);
424 if (!folder.hasWritePermission(user))
425 throw new InsufficientPermissionsException("You don't have the necessary permissions");
427 Folder parent = folder.getParent();
429 if (!folder.getName().equals(folderName) && dao.existsFolderOrFile(parent.getId(), folderName))
430 throw new DuplicateNameException("A folder or file with the name '" + folderName + "' already exists at this level");
432 // Do the actual modification.
433 folder.setName(folderName);
435 return folder.getDTO();
441 * @see gr.ebs.gss.server.ejb.ExternalAPI#createGroup(java.lang.Long,
444 public void createGroup(final Long userId, final String name) throws ObjectNotFoundException, DuplicateNameException {
447 throw new ObjectNotFoundException("No user specified");
448 if (StringUtils.isEmpty(name))
449 throw new ObjectNotFoundException("New group name is empty");
450 if (dao.existsGroup(userId, name))
451 throw new DuplicateNameException("A group with the name '" + name + "' already exists");
453 // TODO: Check permissions
455 final User owner = dao.getEntityById(User.class, userId);
457 // Do the actual work.
458 owner.createGroup(name);
464 * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteGroup(java.lang.Long,
467 public void deleteGroup(final Long userId, final Long groupId) throws ObjectNotFoundException, InsufficientPermissionsException {
470 throw new ObjectNotFoundException("No user specified");
472 throw new ObjectNotFoundException("No group specified");
474 // Do the actual work.
475 final User owner = dao.getEntityById(User.class, userId);
476 final Group group = dao.getEntityById(Group.class, groupId);
477 // Only delete the group if actually owned by the user.
478 if (group.getOwner().equals(owner)) {
479 List<Folder> folders = dao.getFoldersPermittedForGroup(userId, groupId);
480 for (Folder f : folders){
481 f.getPermissions().removeAll(group.getPermissions());
482 for(FileHeader file : f.getFiles())
483 file.getPermissions().removeAll(group.getPermissions());
485 List<FileHeader> files = dao.getSharedFilesNotInSharedFolders(userId);
486 for(FileHeader h : files)
487 h.getPermissions().removeAll(group.getPermissions());
488 owner.removeSpecifiedGroup(group);
491 else throw new InsufficientPermissionsException("You are not the owner of this group");
495 public FileHeaderDTO createFile(Long userId, Long folderId, String name, String mimeType, InputStream stream)
496 throws DuplicateNameException, ObjectNotFoundException, GSSIOException,
497 InsufficientPermissionsException, QuotaExceededException {
500 file = uploadFile(stream, userId);
501 } catch ( IOException ioe) {
502 // Supply a more accurate problem description.
503 throw new GSSIOException("Problem creating file",ioe);
505 return createFile(userId, folderId, name, mimeType, file.length(), file.getAbsolutePath());
509 * @see gr.ebs.gss.server.ejb.ExternalAPIRemote#indexFile(java.lang.Long, boolean)
511 public void indexFile(Long fileId, boolean delete) {
512 Connection qConn = null;
513 Session session = null;
514 MessageProducer sender = null;
516 Context jndiCtx = new InitialContext();
517 ConnectionFactory factory = (QueueConnectionFactory) jndiCtx.lookup("java:/JmsXA");
518 Queue queue = (Queue) jndiCtx.lookup("queue/gss-indexingQueue");
519 qConn = factory.createConnection();
520 session = qConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
521 sender = session.createProducer(queue);
523 MapMessage map = session.createMapMessage();
524 map.setObject("id", fileId);
525 map.setBoolean("delete", delete);
528 catch (NamingException e) {
529 logger.error("Index was not updated: ", e);
531 catch (JMSException e) {
532 logger.error("Index was not updated: ", e);
543 catch (JMSException e) {
552 * A helper method that generates a unique file path for a stored file. The
553 * files are stored using random hash names that are distributed evenly in
554 * a 2-level tree of subdirectories named after the first two hex characters
555 * in the name. For example, file ab1234cd5769f will be stored in the path
556 * /file-repository-root/a/b/ab1234cd5769f. The directories will be created
557 * if they don't already exist.
559 * @return a unique new file path
561 private String generateRepositoryFilePath() {
562 String filename = Long.toHexString(random.nextLong());
563 String fileRepositoryPath = getConfiguration().getString("fileRepositoryPath","/tmp");
564 File root = new File(fileRepositoryPath);
567 File firstFolder = new File(root + File.separator + filename.substring(0, 1));
568 if (!firstFolder.exists())
570 File secondFolder = new File(firstFolder + File.separator + filename.substring(1, 2));
571 if (!secondFolder.exists())
572 secondFolder.mkdir();
573 return secondFolder + File.separator + filename;
579 * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteFile(java.lang.Long,
582 public void deleteFile(final Long userId, final Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
585 throw new ObjectNotFoundException("No user specified");
587 throw new ObjectNotFoundException("No file specified");
589 // Do the actual work.
590 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
591 final Folder parent = file.getFolder();
593 throw new ObjectNotFoundException("The specified file has no parent folder");
594 final User user = dao.getEntityById(User.class, userId);
595 if (!file.hasDeletePermission(user))
596 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
597 for (final FileBody body : file.getBodies())
598 deleteActualFile(body.getStoredFilePath());
600 indexFile(fileId, true);
603 private void deleteActualFile(String filePath) {
604 if (filePath == null)
606 File file = new File(filePath);
608 logger.error("Could not delete file " + filePath);
614 * @see gr.ebs.gss.server.ejb.ExternalAPI#createTag(java.lang.Long,
615 * java.lang.Long, java.lang.String)
617 public void createTag(final Long userId, final Long fileHeaderId, final String tag) throws ObjectNotFoundException {
619 throw new ObjectNotFoundException("No user specified");
620 if (fileHeaderId == null)
621 throw new ObjectNotFoundException("No file specified");
622 if (StringUtils.isEmpty(tag))
623 throw new ObjectNotFoundException("Tag is empty");
625 final User user = dao.getEntityById(User.class, userId);
626 final FileHeader fh = dao.getEntityById(FileHeader.class, fileHeaderId);
627 user.addTag(fh, tag);
631 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUserTags(java.lang.Long)
633 @WebMethod(operationName = "getUserTags")
634 public Set<String> getUserTags(final Long userId) throws ObjectNotFoundException {
635 return dao.getUserTags(userId);
639 * @see gr.ebs.gss.server.ejb.ExternalAPI#updateFile(java.lang.Long, java.lang.Long, java.lang.String, java.util.Set)
641 public void updateFile(Long userId, Long fileId, String name, String tagSet) throws ObjectNotFoundException, InsufficientPermissionsException {
643 throw new ObjectNotFoundException("No user specified");
645 throw new ObjectNotFoundException("No file specified");
646 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
647 User user = dao.getEntityById(User.class, userId);
648 if (!file.hasWritePermission(user))
649 throw new InsufficientPermissionsException("User " + user.getId() + " cannot update file " + file.getName() + "(" + file.getId() + ")");
653 List<FileTag> tags = file.getFileTags();
655 if (tagSet != null) {
656 Iterator<FileTag> i = tags.iterator();
657 while (i.hasNext()) {
658 FileTag tag = i.next();
665 StringTokenizer st = new StringTokenizer(tagSet, ",");
666 while (st.hasMoreTokens())
667 new FileTag(user, file, st.nextToken().trim());
670 // Re-index the file if it was modified.
671 if (name != null || tagSet != null)
672 indexFile(fileId, false);
676 public InputStream getFileContents(Long userId, Long fileId)
677 throws ObjectNotFoundException, InsufficientPermissionsException {
679 throw new ObjectNotFoundException("No user specified");
681 throw new ObjectNotFoundException("No file specified");
683 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
684 User user = dao.getEntityById(User.class, userId);
685 if (!header.hasReadPermission(user)) {
686 logger.info("User " + user.getId() + " cannot read file " + header.getName() + "(" + fileId + ")");
687 throw new InsufficientPermissionsException("You don't have the necessary permissions");
690 File f = new File(header.getCurrentBody().getStoredFilePath());
692 return new FileInputStream(f);
693 } catch (FileNotFoundException e) {
694 logger.error("Could not locate the contents of file " + f.getAbsolutePath());
695 throw new ObjectNotFoundException("The file contents could not be located");
700 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFileContents(java.lang.Long, java.lang.Long, java.lang.Long)
702 public InputStream getFileContents(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
704 throw new ObjectNotFoundException("No user specified");
706 throw new ObjectNotFoundException("No file specified");
708 throw new ObjectNotFoundException("No file specified");
710 final FileHeader header = dao.getEntityById(FileHeader.class, fileId);
711 final FileBody body = dao.getEntityById(FileBody.class, bodyId);
712 final User user = dao.getEntityById(User.class, userId);
713 if (!header.hasReadPermission(user)) {
714 logger.info("User " + user.getId() + " cannot read file " + header.getName() + "(" + fileId + ")");
715 throw new InsufficientPermissionsException("You don't have the necessary permissions");
718 File f = new File(body.getStoredFilePath());
720 return new FileInputStream(f);
721 } catch (FileNotFoundException e) {
722 logger.error("Could not locate the contents of file " + f.getAbsolutePath());
723 throw new ObjectNotFoundException("The file contents could not be located");
728 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFile(java.lang.Long, java.lang.Long)
730 public FileHeaderDTO getFile(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
732 throw new ObjectNotFoundException("No user specified");
734 throw new ObjectNotFoundException("No file specified");
735 final User user = dao.getEntityById(User.class, userId);
736 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
737 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
738 throw new InsufficientPermissionsException("You don't have the necessary permissions");
739 return file.getDTO();
743 public FileBodyDTO getFileBody(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
745 throw new ObjectNotFoundException("No user specified");
747 throw new ObjectNotFoundException("No file specified");
748 User user = dao.getEntityById(User.class, userId);
749 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
750 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
751 throw new InsufficientPermissionsException("You don't have the necessary permissions");
752 FileBody body = dao.getEntityById(FileBody.class, bodyId);
753 return body.getDTO();
757 public Object getResourceAtPath(Long ownerId, String path, boolean ignoreDeleted)
758 throws ObjectNotFoundException {
760 throw new ObjectNotFoundException("No user specified");
761 if (StringUtils.isEmpty(path))
762 throw new ObjectNotFoundException("No path specified");
764 User owner = dao.getEntityById(User.class, ownerId);
765 List<String> pathElements = new ArrayList<String>();
766 StringTokenizer st = new StringTokenizer(path, "/");
767 while (st.hasMoreTokens())
768 pathElements.add(st.nextToken());
769 if (pathElements.size() < 1)
770 return getRootFolder(owner.getId());
771 // Store the last element, since it requires special handling.
772 String lastElement = pathElements.remove(pathElements.size() - 1);
773 FolderDTO cursor = getRootFolder(owner.getId());
774 // Traverse and verify the specified folder path.
775 for (String pathElement : pathElements) {
776 cursor = getFolder(cursor.getId(), pathElement);
777 if (cursor.isDeleted())
778 throw new ObjectNotFoundException("Folder " + cursor.getPath() + " not found");
781 // Use the lastElement to retrieve the actual resource.
782 Object resource = null;
784 FileHeaderDTO file = getFile(cursor.getId(), lastElement);
785 if (ignoreDeleted && file.isDeleted())
786 throw new ObjectNotFoundException("Resource not found");
788 } catch (ObjectNotFoundException e) {
789 // Perhaps the requested resource is not a file, so
790 // check for folders as well.
791 FolderDTO folder = getFolder(cursor.getId(), lastElement);
792 if (ignoreDeleted && folder.isDeleted())
793 throw new ObjectNotFoundException("Resource not found");
800 * Retrieve a file for the specified user that has the specified name and
801 * its parent folder has id equal to folderId.
803 * @param userId the ID of the current user
804 * @param folderId the ID of the parent folder
805 * @param name the name of the requested file
806 * @return the file found
807 * @throws ObjectNotFoundException if the specified folder or file was not
808 * found, with the exception message mentioning the precise
811 private FileHeaderDTO getFile(Long folderId, String name) throws ObjectNotFoundException {
812 if (folderId == null)
813 throw new ObjectNotFoundException("No parent folder specified");
814 if (StringUtils.isEmpty(name))
815 throw new ObjectNotFoundException("No file specified");
817 FileHeader file = dao.getFile(folderId, name);
818 return file.getDTO();
822 * Retrieve a folder for the specified user that has the specified name and
823 * its parent folder has id equal to parentId.
825 * @param parentId the ID of the parent folder
826 * @param name the name of the requested folder
827 * @return the folder found
828 * @throws ObjectNotFoundException if the specified folder or parent was not
829 * found, with the exception message mentioning the precise
832 private FolderDTO getFolder(Long parentId, String name) throws ObjectNotFoundException {
833 if (parentId == null)
834 throw new ObjectNotFoundException("No parent folder specified");
835 if (StringUtils.isEmpty(name))
836 throw new ObjectNotFoundException("No folder specified");
838 Folder folder = dao.getFolder(parentId, name);
839 return folder.getDTO();
842 private FileHeaderDTO updateFileContents(Long userId, Long fileId, String mimeType, InputStream resourceInputStream) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
845 file = uploadFile(resourceInputStream, userId);
846 } catch ( IOException ioe) {
847 // Supply a more accurate problem description.
848 throw new GSSIOException("Problem creating file",ioe);
850 return updateFileContents(userId, fileId, mimeType, file.length(), file.getAbsolutePath());
854 public void copyFile(Long userId, Long fileId, String dest) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
856 throw new ObjectNotFoundException("No user specified");
858 throw new ObjectNotFoundException("No file specified");
859 if (StringUtils.isEmpty(dest))
860 throw new ObjectNotFoundException("No destination specified");
862 Object destination = getResourceAtPath(userId, getParentPath(dest), true);
863 if (!(destination instanceof FolderDTO))
864 throw new ObjectNotFoundException("Destination parent folder not found");
865 FolderDTO parent = (FolderDTO) destination;
866 copyFile(userId, fileId, parent.getId(), getLastElement(dest));
870 public void copyFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
872 throw new ObjectNotFoundException("No user specified");
874 throw new ObjectNotFoundException("No owner specified");
876 throw new ObjectNotFoundException("No file specified");
877 if (StringUtils.isEmpty(dest))
878 throw new ObjectNotFoundException("No destination specified");
880 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
881 if (!(destination instanceof FolderDTO))
882 throw new ObjectNotFoundException("Destination parent folder not found");
883 FolderDTO parent = (FolderDTO) destination;
884 copyFile(userId, fileId, parent.getId(), getLastElement(dest));
888 public void copyFile(Long userId, Long fileId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
890 throw new ObjectNotFoundException("No user specified");
892 throw new ObjectNotFoundException("No file specified");
894 throw new ObjectNotFoundException("No destination specified");
895 if (StringUtils.isEmpty(destName))
896 throw new ObjectNotFoundException("No destination file name specified");
898 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
899 Folder destination = dao.getEntityById(Folder.class, destId);
900 User user = dao.getEntityById(User.class, userId);
901 if (!file.hasReadPermission(user) || !destination.hasWritePermission(user))
902 throw new InsufficientPermissionsException("You don't have the necessary permissions");
903 boolean versioned = file.isVersioned();
904 int versionsNumber = file.getBodies().size();
905 FileBody oldestBody = file.getBodies().get(0);
906 assert oldestBody != null;
907 File contents = new File(oldestBody.getStoredFilePath());
909 createFile(user.getId(), destination.getId(), destName, oldestBody.getMimeType(), new FileInputStream(contents));
910 FileHeader copiedFile = dao.getFile(destination.getId(), destName);
911 copiedFile.setVersioned(versioned);
913 if (versionsNumber > 1)
914 for (int i = 1; i < versionsNumber; i++) {
915 FileBody body = file.getBodies().get(i);
917 contents = new File(body.getStoredFilePath());
918 updateFileContents(user.getId(), copiedFile.getId(), body.getMimeType(), new FileInputStream(contents));
920 List<FileTag> tags = file.getFileTags();
921 for (FileTag tag : tags)
922 createTag(userId, copiedFile.getId(), tag.getTag());
924 } catch (FileNotFoundException e) {
925 throw new ObjectNotFoundException("File contents not found for file " + contents.getAbsolutePath());
931 public void copyFolder(Long userId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
933 throw new ObjectNotFoundException("No user specified");
934 if (folderId == null)
935 throw new ObjectNotFoundException("No folder specified");
936 if (StringUtils.isEmpty(dest))
937 throw new ObjectNotFoundException("No destination specified");
939 Object destination = getResourceAtPath(userId, getParentPath(dest), true);
940 if (!(destination instanceof FolderDTO))
941 throw new ObjectNotFoundException("Destination folder not found");
942 FolderDTO parent = (FolderDTO) destination;
943 copyFolder(userId, folderId, parent.getId(), getLastElement(dest));
947 public void copyFolder(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
949 throw new ObjectNotFoundException("No user specified");
950 if (folderId == null)
951 throw new ObjectNotFoundException("No folder specified");
953 throw new ObjectNotFoundException("No destination specified");
954 if (StringUtils.isEmpty(destName))
955 throw new ObjectNotFoundException("No destination folder name specified");
956 Folder folder = dao.getEntityById(Folder.class, folderId);
957 Folder destination = dao.getEntityById(Folder.class, destId);
958 User user = dao.getEntityById(User.class, userId);
959 if (!destination.hasWritePermission(user) || !folder.hasReadPermission(user))
960 throw new InsufficientPermissionsException("You don't have the necessary permissions");
961 createFolder(user.getId(), destination.getId(), destName);
965 public void copyFolderStructureToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
967 throw new ObjectNotFoundException("No user specified");
969 throw new ObjectNotFoundException("No owner specified");
970 if (folderId == null)
971 throw new ObjectNotFoundException("No folder specified");
972 if (StringUtils.isEmpty(dest))
973 throw new ObjectNotFoundException("No destination specified");
975 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
976 if (!(destination instanceof FolderDTO))
977 throw new ObjectNotFoundException("Destination folder not found");
978 FolderDTO parent = (FolderDTO) destination;
979 copyFolderStructure(userId, folderId, parent.getId(), getLastElement(dest));
983 public void copyFolderStructure(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
985 throw new ObjectNotFoundException("No user specified");
986 if (folderId == null)
987 throw new ObjectNotFoundException("No folder specified");
989 throw new ObjectNotFoundException("No destination specified");
990 if (StringUtils.isEmpty(destName))
991 throw new ObjectNotFoundException("No destination folder name specified");
993 Folder folder = dao.getEntityById(Folder.class, folderId);
994 Folder destination = dao.getEntityById(Folder.class, destId);
995 final User user = dao.getEntityById(User.class, userId);
996 // XXX: quick fix need to copy only visible items to user (Source
998 if (!folder.getOwner().getId().equals(userId) && !folder.hasReadPermission(user))
1000 if(folder.isDeleted())//do not copy trashed folder and contents
1002 if (!destination.hasWritePermission(user) || !folder.hasReadPermission(user))
1003 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1004 createFolder(user.getId(), destination.getId(), destName);
1005 Folder createdFolder = dao.getFolder(destination.getId(), destName);
1006 List<FileHeader> files = folder.getFiles();
1008 for (FileHeader file : files)
1009 if(!file.isDeleted())
1010 copyFile(userId, file.getId(), createdFolder.getId(), file.getName());
1011 List<Folder> subFolders = folder.getSubfolders();
1012 if (subFolders != null)
1013 for (Folder sub : subFolders)
1014 if(!sub.getId().equals(createdFolder.getId()))
1015 copyFolderStructure(userId, sub.getId(), createdFolder.getId(), sub.getName());
1020 * For a provided path, remove the last element and return the rest, that is
1021 * the path of the parent folder.
1023 * @param path the specified path
1024 * @return the path of the parent folder
1025 * @throws ObjectNotFoundException if the provided string contains no path
1028 private String getParentPath(String path) throws ObjectNotFoundException {
1029 int lastDelimiter = path.lastIndexOf('/');
1030 if (lastDelimiter == 0)
1032 if (lastDelimiter == -1)
1034 throw new ObjectNotFoundException("There is no parent in the path: " + path);
1035 else if (lastDelimiter < path.length() - 1)
1036 // Return the part before the delimiter.
1037 return path.substring(0, lastDelimiter);
1039 // Remove the trailing delimiter and then recurse.
1040 String strippedTrail = path.substring(0, lastDelimiter);
1041 return getParentPath(strippedTrail);
1046 * Get the last element in a path that denotes the file or folder name.
1048 * @param path the provided path
1049 * @return the last element in the path
1051 private String getLastElement(String path) {
1052 int lastDelimiter = path.lastIndexOf('/');
1053 if (lastDelimiter == -1)
1056 else if (lastDelimiter < path.length() - 1)
1057 // Return the part after the delimiter.
1058 return path.substring(lastDelimiter + 1);
1060 // Remove the trailing delimiter and then recurse.
1061 String strippedTrail = path.substring(0, lastDelimiter);
1062 return getLastElement(strippedTrail);
1067 public void moveFileToTrash(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1069 throw new ObjectNotFoundException("No user specified");
1071 throw new ObjectNotFoundException("No file specified");
1073 // Do the actual work.
1074 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1075 Folder parent = file.getFolder();
1077 throw new ObjectNotFoundException("The specified file has no parent folder");
1078 User user = dao.getEntityById(User.class, userId);
1079 if (!file.hasDeletePermission(user))
1080 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
1082 file.setDeleted(true);
1087 public void moveFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, InsufficientPermissionsException, QuotaExceededException {
1089 throw new ObjectNotFoundException("No user specified");
1090 if (ownerId == null)
1091 throw new ObjectNotFoundException("No owner specified");
1093 throw new ObjectNotFoundException("No file specified");
1094 if (StringUtils.isEmpty(dest))
1095 throw new ObjectNotFoundException("No destination specified");
1097 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1098 if (!(destination instanceof FolderDTO))
1099 throw new ObjectNotFoundException("Destination parent folder not found");
1100 FolderDTO parent = (FolderDTO) destination;
1101 moveFile(userId, fileId, parent.getId(), getLastElement(dest));
1105 public void moveFile(Long userId, Long fileId, Long destId, String destName) throws InsufficientPermissionsException, ObjectNotFoundException, QuotaExceededException {
1107 throw new ObjectNotFoundException("No user specified");
1109 throw new ObjectNotFoundException("No file specified");
1111 throw new ObjectNotFoundException("No destination specified");
1112 if (StringUtils.isEmpty(destName))
1113 throw new ObjectNotFoundException("No destination file name specified");
1115 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1116 Folder destination = dao.getEntityById(Folder.class, destId);
1118 User owner = dao.getEntityById(User.class, userId);
1119 if (!file.hasDeletePermission(owner) || !destination.hasWritePermission(owner))
1120 throw new InsufficientPermissionsException("User " + owner.getId() + " cannot move file " + file.getName() + "(" + file.getId() + ")");
1122 // if the destination folder belongs to another user:
1123 if (!file.getOwner().equals(destination.getOwner())) {
1124 // (a) check if the destination quota allows the move
1125 if(getQuotaLeft(destination.getOwner().getId()) < file.getTotalSize())
1126 throw new QuotaExceededException("Not enough free space available");
1127 User newOwner = destination.getOwner();
1128 // (b) if quota OK, change the owner of the file
1129 file.setOwner(newOwner);
1130 // if the file has no permission for the new owner, add it
1131 Permission ownerPermission = null;
1132 for (final Permission p : file.getPermissions())
1133 if (p.getUser() != null)
1134 if (p.getUser().equals(newOwner)) {
1135 ownerPermission = p;
1138 if (ownerPermission == null) {
1139 ownerPermission = new Permission();
1140 ownerPermission.setUser(newOwner);
1141 file.addPermission(ownerPermission);
1143 ownerPermission.setRead(true);
1144 ownerPermission.setWrite(true);
1145 ownerPermission.setModifyACL(true);
1147 // move the file to the destination folder
1148 file.setFolder(destination);
1152 public void moveFolderToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1154 throw new ObjectNotFoundException("No user specified");
1155 if (ownerId == null)
1156 throw new ObjectNotFoundException("No owner specified");
1157 if (folderId == null)
1158 throw new ObjectNotFoundException("No folder specified");
1159 if (StringUtils.isEmpty(dest))
1160 throw new ObjectNotFoundException("No destination specified");
1162 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1163 if (!(destination instanceof FolderDTO))
1164 throw new ObjectNotFoundException("Destination parent folder not found");
1165 FolderDTO parent = (FolderDTO) destination;
1166 moveFolder(userId, folderId, parent.getId(), getLastElement(dest));
1170 public void moveFolder(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1171 // TODO Simple Move and delete of original folder, in production
1172 // scenario we must first check individual files and folders permissions
1173 copyFolderStructure(userId, folderId, destId, destName);
1174 deleteFolder(userId, folderId);
1178 * @see gr.ebs.gss.server.ejb.ExternalAPI#getDeletedFiles(java.lang.Long)
1180 public List<FileHeaderDTO> getDeletedFiles(Long userId) throws ObjectNotFoundException {
1183 throw new ObjectNotFoundException("No user specified");
1185 // Do the actual work.
1186 final List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1187 final List<FileHeader> files = dao.getDeletedFiles(userId);
1188 for (final FileHeader f : files)
1189 result.add(f.getDTO());
1194 public void removeFileFromTrash(Long userId, Long fileId)
1195 throws ObjectNotFoundException, InsufficientPermissionsException {
1197 throw new ObjectNotFoundException("No user specified");
1199 throw new ObjectNotFoundException("No file specified");
1201 // Do the actual work.
1202 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1203 Folder parent = file.getFolder();
1205 throw new ObjectNotFoundException("The specified file has no parent folder");
1206 User user = dao.getEntityById(User.class, userId);
1207 if (!file.hasDeletePermission(user))
1208 throw new InsufficientPermissionsException("User " + user.getUsername() +
1209 " cannot restore file " + file.getName());
1211 file.setDeleted(false);
1216 public void moveFolderToTrash(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
1218 throw new ObjectNotFoundException("No user specified");
1219 if (folderId == null)
1220 throw new ObjectNotFoundException("No folder specified");
1221 Folder folder = dao.getEntityById(Folder.class, folderId);
1222 User user = dao.getEntityById(User.class, userId);
1223 if (!folder.hasDeletePermission(user))
1224 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1225 folder.setDeleted(true);
1227 for (FileHeader file : folder.getFiles())
1228 moveFileToTrash(userId, file.getId());
1229 for (Folder subFolder : folder.getSubfolders())
1230 moveFolderToTrash(userId, subFolder.getId());
1235 public void removeFolderFromTrash(Long userId, Long folderId)
1236 throws ObjectNotFoundException, InsufficientPermissionsException {
1238 throw new ObjectNotFoundException("No user specified");
1239 if (folderId == null)
1240 throw new ObjectNotFoundException("No folder specified");
1241 Folder folder = dao.getEntityById(Folder.class, folderId);
1242 User user = dao.getEntityById(User.class, userId);
1243 if (!folder.hasDeletePermission(user))
1244 throw new InsufficientPermissionsException("User " + user.getUsername() +
1245 " cannot restore folder " + folder.getName());
1246 folder.setDeleted(false);
1247 for (FileHeader file : folder.getFiles())
1248 removeFileFromTrash(userId, file.getId());
1249 for (Folder subFolder : folder.getSubfolders())
1250 removeFolderFromTrash(userId, subFolder.getId());
1255 public List<FolderDTO> getDeletedRootFolders(Long userId) throws ObjectNotFoundException {
1256 List<Folder> folders = dao.getDeletedRootFolders(userId);
1257 List<FolderDTO> result = new ArrayList<FolderDTO>();
1258 for (Folder folder : folders)
1259 result.add(folder.getDTO());
1264 public void emptyTrash(Long userId) throws ObjectNotFoundException, InsufficientPermissionsException {
1265 List<FolderDTO> deletedRootFolders = getDeletedRootFolders(userId);
1266 for (FolderDTO fdto : deletedRootFolders)
1267 deleteFolder(userId, fdto.getId());
1268 List<FileHeaderDTO> deletedFiles = getDeletedFiles(userId);
1269 for (FileHeaderDTO filedto : deletedFiles)
1270 deleteFile(userId, filedto.getId());
1274 public void restoreTrash(Long userId) throws ObjectNotFoundException, InsufficientPermissionsException {
1275 List<FolderDTO> deletedRootFolders = getDeletedRootFolders(userId);
1276 for (FolderDTO fdto : deletedRootFolders)
1277 removeFolderFromTrash(userId, fdto.getId());
1278 List<FileHeaderDTO> deletedFiles = getDeletedFiles(userId);
1279 for (FileHeaderDTO filedto : deletedFiles)
1280 removeFileFromTrash(userId, filedto.getId());
1284 public User createUser(String username, String name, String mail) throws ObjectNotFoundException {
1285 if (username == null)
1286 throw new ObjectNotFoundException("No username specified");
1288 throw new ObjectNotFoundException("No name specified");
1290 User user = new User();
1291 user.setUsername(username);
1293 user.setEmail(mail);
1294 Date now = new Date();
1295 AuditInfo auditInfo = new AuditInfo();
1296 auditInfo.setCreationDate(now);
1297 auditInfo.setModificationDate(now);
1298 user.setAuditInfo(auditInfo);
1299 user.generateAuthToken();
1300 user.generateWebDAVPassword();
1302 // Make sure we get an ID in the user object.
1304 // Create the root folder for the user.
1305 createFolder(user.getName(), null, user);
1310 public User findUserByEmail(String email) {
1311 return dao.findUserByEmail(email);
1315 public void updateUser(User user) {
1320 public User updateUser(String username, String name, String mail) throws ObjectNotFoundException {
1321 if (username == null)
1322 throw new ObjectNotFoundException("No username specified");
1324 User user = dao.getUser(username);
1326 user.setEmail(mail);
1331 public User findUser(String username) {
1332 if (username == null)
1334 return dao.findUser(username);
1338 public User updateUserToken(Long userId) throws ObjectNotFoundException {
1340 throw new ObjectNotFoundException("No user specified");
1341 User user = dao.getEntityById(User.class, userId);
1342 user.generateAuthToken();
1347 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFolderPermissions(java.lang.Long, java.lang.Long)
1350 public Set<PermissionDTO> getFolderPermissions(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
1352 throw new ObjectNotFoundException("No user specified");
1353 if (folderId == null)
1354 throw new ObjectNotFoundException("No folder specified");
1355 User user = dao.getEntityById(User.class, userId);
1356 Folder folder = dao.getEntityById(Folder.class, folderId);
1357 if(!folder.hasReadPermission(user))
1358 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1359 Set<Permission> perms = folder.getPermissions();
1360 Set<PermissionDTO> result = new LinkedHashSet<PermissionDTO>();
1361 for (Permission perm : perms)
1362 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId()))
1363 result.add(perm.getDTO());
1364 for (Permission perm : perms)
1365 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId())) {
1367 result.add(perm.getDTO());
1373 * @see gr.ebs.gss.server.ejb.ExternalAPI#setFolderPermissions(java.lang.Long, java.lang.Long, java.util.Set)
1376 public void setFolderPermissions(Long userId, Long folderId, Set<PermissionDTO> permissions) throws ObjectNotFoundException, InsufficientPermissionsException {
1378 throw new ObjectNotFoundException("No user specified");
1379 if (folderId == null)
1380 throw new ObjectNotFoundException("No folder specified");
1381 User user = dao.getEntityById(User.class, userId);
1382 Folder folder = dao.getEntityById(Folder.class, folderId);
1383 if(!folder.hasModifyACLPermission(user))
1384 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1385 // Delete previous entries
1386 for (Permission perm: folder.getPermissions())
1388 folder.getPermissions().clear();
1389 for (PermissionDTO dto : permissions) {
1390 if (dto.getUser()!=null && dto.getUser().getId().equals(folder.getOwner().getId()) && (!dto.hasRead() || !dto.hasWrite() || !dto.hasModifyACL()))
1391 throw new InsufficientPermissionsException("Can't remove permissions from owner");
1392 // Don't include 'empty' permission
1393 if (!dto.getRead() && !dto.getWrite() && !dto.getModifyACL()) continue;
1394 folder.addPermission(getPermission(dto));
1397 for (FileHeader fh : folder.getFiles())
1398 setFilePermissions(userId, fh.getId(), fh.isReadForAll(), permissions);
1399 for (Folder sub : folder.getSubfolders())
1400 setFolderPermissions(userId, sub.getId(), permissions);
1403 private Permission getPermission(PermissionDTO dto) throws ObjectNotFoundException {
1404 Permission res = new Permission();
1405 if (dto.getGroup() != null)
1406 res.setGroup(dao.getEntityById(Group.class, dto.getGroup().getId()));
1407 else if (dto.getUser() != null)
1408 if (dto.getUser().getId() == null)
1409 res.setUser(dao.getUser(dto.getUser().getUsername()));
1411 res.setUser(dao.getEntityById(User.class, dto.getUser().getId()));
1412 res.setRead(dto.hasRead());
1413 res.setWrite(dto.hasWrite());
1414 res.setModifyACL(dto.hasModifyACL());
1419 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsersByUserNameLike(java.lang.String)
1422 public List<UserDTO> getUsersByUserNameLike(String username) {
1423 List<User> users = dao.getUsersByUserNameLike(username);
1424 List<UserDTO> result = new ArrayList<UserDTO>();
1425 for (User u : users)
1426 result.add(u.getDTO());
1432 * @see gr.ebs.gss.server.ejb.ExternalAPI#addUserToGroup(java.lang.Long, java.lang.Long, java.lang.Long)
1435 public void addUserToGroup(Long userId, Long groupId, Long userToAddId) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
1437 throw new ObjectNotFoundException("No user specified");
1438 if (groupId == null)
1439 throw new ObjectNotFoundException("No group specified");
1440 if (userToAddId == null)
1441 throw new ObjectNotFoundException("No user to add specified");
1442 User user = dao.getEntityById(User.class, userId);
1443 Group group = dao.getEntityById(Group.class, groupId);
1444 if (!group.getOwner().equals(user))
1445 throw new InsufficientPermissionsException();
1446 User userToAdd = dao.getEntityById(User.class, userToAddId);
1447 if (group.contains(userToAdd))
1448 throw new DuplicateNameException("User already exists in group");
1449 group.getMembers().add(userToAdd);
1455 public void invalidateUserToken(Long userId) throws ObjectNotFoundException {
1457 throw new ObjectNotFoundException("No user specified");
1458 User user = dao.getEntityById(User.class, userId);
1459 user.invalidateAuthToken();
1464 public List<FolderDTO> getSharedRootFolders(Long userId) throws ObjectNotFoundException {
1466 throw new ObjectNotFoundException("No user specified");
1467 List<Folder> folders = dao.getSharedRootFolders(userId);
1468 List<FolderDTO> result = new ArrayList<FolderDTO>();
1469 for (Folder f : folders) {
1470 FolderDTO dto = f.getDTO();
1471 dto.setSubfolders(getSharedSubfolders(userId, f.getId()));
1478 * @see gr.ebs.gss.server.ejb.ExternalAPI#removeMemberFromGroup(java.lang.Long, java.lang.Long, java.lang.Long)
1481 public void removeMemberFromGroup(Long userId, Long groupId, Long memberId) throws ObjectNotFoundException, InsufficientPermissionsException {
1483 throw new ObjectNotFoundException("No user specified");
1484 if (groupId == null)
1485 throw new ObjectNotFoundException("No group specified");
1486 if (memberId == null)
1487 throw new ObjectNotFoundException("No member specified");
1488 User owner = dao.getEntityById(User.class, userId);
1489 Group group = dao.getEntityById(Group.class, groupId);
1490 User member = dao.getEntityById(User.class, memberId);
1491 if (!group.getOwner().equals(owner))
1492 throw new InsufficientPermissionsException("User is not the owner of the group");
1493 group.removeMemberFromGroup(member);
1499 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsersSharingFoldersForUser(java.lang.Long)
1502 public List<UserDTO> getUsersSharingFoldersForUser(Long userId) throws ObjectNotFoundException {
1503 List<User> users = dao.getUsersSharingFoldersForUser(userId);
1504 List<User> usersFiles = dao.getUsersSharingFilesForUser(userId);
1505 List<UserDTO> res = new ArrayList<UserDTO>();
1506 for (User u : users)
1507 res.add(u.getDTO());
1508 for(User fu : usersFiles)
1509 if(!users.contains(fu))
1510 res.add(fu.getDTO());
1515 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFilePermissions(java.lang.Long, java.lang.Long)
1518 public Set<PermissionDTO> getFilePermissions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1520 throw new ObjectNotFoundException("No user specified");
1522 throw new ObjectNotFoundException("No folder specified");
1523 User user = dao.getEntityById(User.class, userId);
1524 FileHeader folder = dao.getEntityById(FileHeader.class, fileId);
1525 if(!folder.hasReadPermission(user))
1526 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1527 Set<Permission> perms = folder.getPermissions();
1528 Set<PermissionDTO> result = new LinkedHashSet<PermissionDTO>();
1529 for (Permission perm : perms)
1530 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId()))
1531 result.add(perm.getDTO());
1532 for (Permission perm : perms)
1533 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId())) {
1535 result.add(perm.getDTO());
1540 public void setFilePermissions(Long userId, Long fileId, Boolean readForAll, Set<PermissionDTO> permissions) throws ObjectNotFoundException, InsufficientPermissionsException {
1542 throw new ObjectNotFoundException("No user specified");
1544 throw new ObjectNotFoundException("No folder specified");
1546 User user = dao.getEntityById(User.class, userId);
1547 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1548 if(!file.hasModifyACLPermission(user))
1549 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1551 if (readForAll != null)
1552 if (user.equals(file.getOwner()))
1553 file.setReadForAll(readForAll);
1555 throw new InsufficientPermissionsException("Only the owner can change the read-for-all flag");
1557 // Update the file if there was a change.
1558 if (readForAll != null || permissions != null && !permissions.isEmpty()) {
1559 if (permissions != null && !permissions.isEmpty()) {
1560 // Delete previous entries
1561 for (Permission perm: file.getPermissions())
1563 file.getPermissions().clear();
1564 for (PermissionDTO dto : permissions) {
1565 if (dto.getUser()!=null && dto.getUser().getId().equals(file.getOwner().getId()) && (!dto.hasRead() || !dto.hasWrite() || !dto.hasModifyACL()))
1566 throw new InsufficientPermissionsException("Can't remove permissions from owner");
1567 // Don't include 'empty' permission
1568 if (!dto.getRead() && !dto.getWrite() && !dto.getModifyACL()) continue;
1569 file.addPermission(getPermission(dto));
1578 public List<FileHeaderDTO> getSharedFilesNotInSharedFolders(Long userId) throws ObjectNotFoundException {
1580 throw new ObjectNotFoundException("No user specified");
1581 List<FileHeader> files = dao.getSharedFilesNotInSharedFolders(userId);
1582 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1583 for (FileHeader f : files)
1584 result.add(f.getDTO());
1589 public List<FileHeaderDTO> getSharedFiles(Long userId) throws ObjectNotFoundException {
1591 throw new ObjectNotFoundException("No user specified");
1592 List<FileHeader> files = dao.getSharedFiles(userId);
1593 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1594 for (FileHeader f : files)
1595 result.add(f.getDTO());
1600 public List<FolderDTO> getSharedFolders(Long userId) throws ObjectNotFoundException {
1602 throw new ObjectNotFoundException("No user specified");
1603 List<Folder> folders = dao.getSharedFolders(userId);
1604 List<FolderDTO> result = new ArrayList<FolderDTO>();
1605 for (Folder f : folders)
1606 result.add(f.getDTO());
1611 * @see gr.ebs.gss.server.ejb.ExternalAPI#getSharedFiles(java.lang.Long, java.lang.Long)
1614 public List<FileHeaderDTO> getSharedFiles(Long ownerId, Long callingUserId) throws ObjectNotFoundException {
1615 if (ownerId == null)
1616 throw new ObjectNotFoundException("No owner specified");
1617 if (callingUserId == null)
1618 throw new ObjectNotFoundException("No calling user specified");
1619 List<FileHeader> folders = dao.getSharedFiles(ownerId, callingUserId);
1620 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1621 for (FileHeader f : folders)
1622 result.add(f.getDTO());
1627 public List<FolderDTO> getSharedRootFolders(Long ownerId, Long callingUserId) throws ObjectNotFoundException {
1628 if (ownerId == null)
1629 throw new ObjectNotFoundException("No owner specified");
1630 if (callingUserId == null)
1631 throw new ObjectNotFoundException("No calling user specified");
1632 List<Folder> folders = dao.getSharedRootFolders(ownerId, callingUserId);
1633 List<FolderDTO> result = new ArrayList<FolderDTO>();
1634 for (Folder f : folders) {
1635 FolderDTO dto = f.getDTO();
1636 dto.setSubfolders(getSharedSubfolders(ownerId, callingUserId, f.getId()));
1644 public List<FolderDTO> getSharedSubfolders(Long userId, Long folderId) throws ObjectNotFoundException {
1646 throw new ObjectNotFoundException("No user specified");
1647 if (folderId == null)
1648 throw new ObjectNotFoundException("No folder specified");
1649 User user = dao.getEntityById(User.class, userId);
1650 Folder folder = dao.getEntityById(Folder.class, folderId);
1651 List<FolderDTO> result = new ArrayList<FolderDTO>();
1652 if (folder.isShared(user))
1653 for (Folder f : folder.getSubfolders())
1654 if (f.isShared(user) && !f.isDeleted())
1655 result.add(f.getDTO());
1660 public List<FolderDTO> getSharedSubfolders(Long userId, Long callingUserId, Long folderId) throws ObjectNotFoundException {
1662 throw new ObjectNotFoundException("No user specified");
1663 if (callingUserId == null)
1664 throw new ObjectNotFoundException("No user specified");
1665 if (folderId == null)
1666 throw new ObjectNotFoundException("No folder specified");
1667 User user = dao.getEntityById(User.class, callingUserId);
1668 Folder folder = dao.getEntityById(Folder.class, folderId);
1669 List<FolderDTO> result = new ArrayList<FolderDTO>();
1670 if (folder.isSharedForOtherUser(user))
1671 for (Folder f : folder.getSubfolders())
1672 if (f.isSharedForOtherUser(user) && !f.isDeleted()){
1673 FolderDTO dto = f.getDTO();
1674 dto.setSubfolders(getSharedSubfolders(userId, callingUserId, dto.getId()));
1682 * @see gr.ebs.gss.server.ejb.ExternalAPI#searchFiles(java.lang.Long, java.lang.String)
1685 public List<FileHeaderDTO> searchFiles(Long userId, String query) throws ObjectNotFoundException {
1687 throw new ObjectNotFoundException("No user specified");
1688 User user = getUser(userId);
1690 throw new ObjectNotFoundException("No query specified");
1691 List<FileHeader> files = search(user.getId(), query);
1692 List<FileHeaderDTO> res = new ArrayList<FileHeaderDTO>();
1693 for(FileHeader f : files)
1694 res.add(f.getDTO());
1699 * Performs the actuals search on the solr server and returns the results
1701 * We have to use the dismax query type (instead of the
1702 * standard) because it allows for search time field boosting. This is because we can't use indexing
1703 * time field boosting due to the patched rich indexing API that does not allow it
1707 * @return a List of FileHeader objects
1709 private List<FileHeader> search(Long userId, String query) {
1711 HttpClient httpClient = new HttpClient();
1713 GetMethod method = new GetMethod(getConfiguration().getString("solrSelectUrl"));
1714 NameValuePair[] params = {new NameValuePair("qt", "dismax"),
1715 new NameValuePair("q", query),
1716 new NameValuePair("sort", "score desc"),
1717 new NameValuePair("indent", "on")};
1718 method.setQueryString(params);
1721 String response = null;
1723 statusCode = httpClient.executeMethod(method);
1724 logger.debug("HTTP status: " + statusCode);
1725 response = method.getResponseBodyAsString();
1726 logger.debug(response);
1728 if (statusCode != 200 && retryCount < 3)
1730 Thread.sleep(3000); //Give Solr a little time to be available
1731 } catch (InterruptedException e) {
1733 } while (statusCode != 200 && retryCount < 3);
1734 if (statusCode != 200)
1735 throw new EJBException("Search query return error:\n" + response);
1737 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
1738 DocumentBuilder db = dbf.newDocumentBuilder();
1739 Document doc = db.parse(method.getResponseBodyAsStream());
1740 method.releaseConnection();
1742 Node root = doc.getElementsByTagName("response").item(0);
1743 Node lst = root.getFirstChild().getNextSibling();
1744 Node status = lst.getFirstChild().getNextSibling();
1745 if (status.getAttributes().getNamedItem("name").getNodeValue().equals("status") &&
1746 status.getTextContent().equals("0")) {
1747 List<FileHeader> fileResult = new ArrayList<FileHeader>();
1748 Node result = lst.getNextSibling().getNextSibling();
1749 NodeList docs = result.getChildNodes();
1750 User user = getUser(userId);
1751 for (int i=1; i<docs.getLength(); i=i+2) {
1752 Node d = docs.item(i);
1753 NodeList docData = d.getChildNodes();
1754 for (int j=1; j<docData.getLength(); j=j+2) {
1755 Node dd = docData.item(j);
1756 if (dd.getAttributes().item(0).getNodeName().equals("name") &&
1757 dd.getAttributes().item(0).getNodeValue().equals("id")) {
1758 Long fileId = Long.valueOf(dd.getTextContent());
1760 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1761 if (file.hasReadPermission(user)) {
1762 fileResult.add(file);
1763 logger.debug("File added " + fileId);
1765 } catch (ObjectNotFoundException e) {
1766 logger.warn("Search result not found", e);
1773 throw new EJBException();
1774 } catch (HttpException e) {
1775 throw new EJBException(e);
1776 } catch (IOException e) {
1777 throw new EJBException(e);
1778 } catch (SAXException e) {
1779 throw new EJBException(e);
1780 } catch (ParserConfigurationException e) {
1781 throw new EJBException(e);
1782 } catch (ObjectNotFoundException e) {
1783 throw new EJBException(e);
1788 * @see gr.ebs.gss.server.ejb.ExternalAPI#copyFiles(java.lang.Long, java.util.List, java.lang.Long)
1791 public void copyFiles(Long userId, List<Long> fileIds, Long destId) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
1792 for(Long l : fileIds){
1793 FileHeader file = dao.getEntityById(FileHeader.class, l);
1794 copyFile(userId, l, destId, file.getName());
1801 * @see gr.ebs.gss.server.ejb.ExternalAPI#moveFiles(java.lang.Long, java.util.List, java.lang.Long)
1804 public void moveFiles(Long userId, List<Long> fileIds, Long destId) throws InsufficientPermissionsException, ObjectNotFoundException, QuotaExceededException {
1805 for(Long l : fileIds){
1806 FileHeader file = dao.getEntityById(FileHeader.class, l);
1807 moveFile(userId, l, destId, file.getName());
1813 * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteFiles(java.lang.Long, java.util.List)
1816 public void deleteFiles(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1818 throw new ObjectNotFoundException("No user specified");
1819 final User user = dao.getEntityById(User.class, userId);
1820 List<String> filesToRemove = new ArrayList<String>();
1821 //first delete database objects
1822 for(Long fileId : fileIds){
1824 throw new ObjectNotFoundException("No file specified");
1825 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1826 final Folder parent = file.getFolder();
1828 throw new ObjectNotFoundException("The specified file has no parent folder");
1829 if (!file.hasDeletePermission(user))
1830 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
1832 parent.removeFile(file);
1833 for (final FileBody body : file.getBodies())
1834 filesToRemove.add(body.getStoredFilePath());
1837 //then remove physical files if everything is ok
1838 for(String physicalFileName : filesToRemove)
1839 deleteActualFile(physicalFileName);
1840 //then unindex deleted files
1841 for(Long fileId : fileIds)
1842 indexFile(fileId, true);
1847 * @see gr.ebs.gss.server.ejb.ExternalAPI#moveFilesToTrash(java.lang.Long, java.util.List)
1850 public void moveFilesToTrash(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1851 for(Long l : fileIds)
1852 moveFileToTrash(userId, l);
1857 public void removeFilesFromTrash(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1858 for(Long l : fileIds)
1859 removeFileFromTrash(userId, l);
1864 public Nonce createNonce(Long userId) throws ObjectNotFoundException {
1866 throw new ObjectNotFoundException("No user specified");
1867 User user = dao.getEntityById(User.class, userId);
1868 Nonce nonce = Nonce.createNonce(user.getId());
1874 public Nonce getNonce(String nonce, Long userId) throws ObjectNotFoundException {
1876 throw new ObjectNotFoundException("No user specified");
1878 throw new ObjectNotFoundException("No nonce specified");
1879 return dao.getNonce(nonce, userId);
1883 public void removeNonce(Long id) throws ObjectNotFoundException {
1885 throw new ObjectNotFoundException("No nonce specified");
1886 Nonce nonce = dao.getEntityById(Nonce.class, id);
1891 public void activateUserNonce(Long userId, String nonce, Date nonceExpiryDate) throws ObjectNotFoundException {
1893 throw new ObjectNotFoundException("No user specified");
1894 User user = dao.getEntityById(User.class, userId);
1895 user.setNonce(nonce);
1896 user.setNonceExpiryDate(nonceExpiryDate);
1900 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUserStatistics(java.lang.Long)
1903 public StatsDTO getUserStatistics(Long userId) throws ObjectNotFoundException {
1905 throw new ObjectNotFoundException("No user specified");
1906 StatsDTO stats = new StatsDTO();
1907 stats.setFileCount(dao.getFileCount(userId));
1908 Long fileSize = dao.getFileSize(userId);
1909 stats.setFileSize(fileSize);
1910 Long quota = getQuota(userId);
1911 Long quotaLeft = quota - fileSize;
1912 stats.setQuotaLeftSize(quotaLeft);
1917 * @see gr.ebs.gss.server.ejb.ExternalAPI#getVersions(java.lang.Long, java.lang.Long)
1920 public List<FileBodyDTO> getVersions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1922 throw new ObjectNotFoundException("No user specified");
1924 throw new ObjectNotFoundException("No file specified");
1925 User user = dao.getEntityById(User.class, userId);
1926 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
1927 if(!header.hasReadPermission(user))
1928 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1929 List<FileBodyDTO> result = new LinkedList<FileBodyDTO>();
1930 for(int i = header.getBodies().size()-1 ; i>=0; i--)
1931 result.add(header.getBodies().get(i).getDTO());
1936 * @see gr.ebs.gss.server.ejb.ExternalAPI#removeVersion(java.lang.Long, java.lang.Long, java.lang.Long)
1939 public void removeVersion(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
1941 throw new ObjectNotFoundException("No user specified");
1943 throw new ObjectNotFoundException("No file specified");
1945 throw new ObjectNotFoundException("No body specified");
1946 User user = dao.getEntityById(User.class, userId);
1947 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
1948 if(!header.hasWritePermission(user))
1949 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1950 FileBody body = dao.getEntityById(FileBody.class, bodyId);
1951 if(body.equals(header.getCurrentBody())){
1953 if(header.getBodies().size() == 1)
1954 throw new InsufficientPermissionsException("You cant delete this version, Delete file instead!");
1955 for(FileBody b : header.getBodies())
1956 if(b.getVersion() == body.getVersion()-1)
1957 header.setCurrentBody(b);
1959 deleteActualFile(body.getStoredFilePath());
1960 header.getBodies().remove(body);
1966 public void restoreVersion(Long userId, Long fileId, int version) throws ObjectNotFoundException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1968 throw new ObjectNotFoundException("No user specified");
1970 throw new ObjectNotFoundException("No file specified");
1971 User user = dao.getEntityById(User.class, userId);
1972 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
1973 if(!header.hasWritePermission(user))
1974 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1975 FileBody body = dao.getFileVersion(fileId, version);
1976 final File fileContents = new File(body.getStoredFilePath());
1979 updateFileContents(userId, fileId, body.getMimeType(), new FileInputStream(fileContents) );
1980 } catch (FileNotFoundException e) {
1981 throw new GSSIOException(e);
1987 * @see gr.ebs.gss.server.ejb.ExternalAPI#removeOldVersions(java.lang.Long, java.lang.Long)
1990 public void removeOldVersions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1992 throw new ObjectNotFoundException("No user specified");
1994 throw new ObjectNotFoundException("No file specified");
1995 User user = dao.getEntityById(User.class, userId);
1996 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
1997 if(!header.hasWritePermission(user))
1998 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1999 Iterator<FileBody> it = header.getBodies().iterator();
2000 while(it.hasNext()){
2001 FileBody body = it.next();
2002 if(!body.equals(header.getCurrentBody())){
2003 deleteActualFile(body.getStoredFilePath());
2008 header.getCurrentBody().setVersion(1);
2013 * @see gr.ebs.gss.server.ejb.ExternalAPI#toggleFileVersioning(java.lang.Long, java.lang.Long, boolean)
2016 public void toggleFileVersioning(Long userId, Long fileId, boolean versioned) throws ObjectNotFoundException, InsufficientPermissionsException {
2018 throw new ObjectNotFoundException("No user specified");
2020 throw new ObjectNotFoundException("No file specified");
2021 User user = dao.getEntityById(User.class, userId);
2022 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
2023 if(!header.hasWritePermission(user))
2024 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2025 if(!header.isVersioned() == versioned){
2026 if(header.isVersioned())
2027 removeOldVersions(userId, fileId);
2028 header.setVersioned(versioned);
2034 * Gets the quota left for specified userId
2038 private Long getQuotaLeft(Long userId){
2039 Long fileSize = dao.getFileSize(userId);
2040 Long quota = getQuota(userId);
2041 return quota - fileSize;
2045 * Gets the quota for specified userId
2049 private Long getQuota(@SuppressWarnings("unused") Long userId){
2050 Long quota = getConfiguration().getLong("quota", new Long(52428800L));
2054 public void rebuildSolrIndex() {
2055 MessageProducer sender = null;
2056 Session session = null;
2057 Connection qConn = null;
2059 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
2060 DocumentBuilder db = dbf.newDocumentBuilder();
2061 Document doc = db.newDocument();
2062 Node root = doc.createElement("delete");
2063 doc.appendChild(root);
2064 Node queryNode = doc.createElement("query");
2065 root.appendChild(queryNode);
2066 queryNode.appendChild(doc.createTextNode("*:*"));
2068 TransformerFactory fact = TransformerFactory.newInstance();
2069 Transformer trans = fact.newTransformer();
2070 trans.setOutputProperty(OutputKeys.INDENT, "yes");
2071 StringWriter sw = new StringWriter();
2072 StreamResult sr = new StreamResult(sw);
2073 DOMSource source = new DOMSource(doc);
2074 trans.transform(source, sr);
2075 logger.debug(sw.toString());
2077 HttpClient httpClient = new HttpClient();
2078 PostMethod method = new PostMethod(getConfiguration().getString("solrUpdateUrl"));
2079 method.setRequestEntity(new StringRequestEntity(sw.toString()));
2082 String response = null;
2084 statusCode = httpClient.executeMethod(method);
2085 logger.debug("HTTP status: " + statusCode);
2086 response = method.getResponseBodyAsString();
2087 logger.debug(response);
2089 if (statusCode != 200 && retryCount < 3)
2091 Thread.sleep(10000); //Give Solr a little time to be available
2092 } catch (InterruptedException e) {
2094 } while (statusCode != 200 && retryCount < 3);
2095 method.releaseConnection();
2096 if (statusCode != 200)
2097 throw new EJBException("Cannot clear Solr index. Solr response is:\n" + response);
2098 List<Long> fileIds = dao.getAllFileIds();
2100 Context jndiCtx = new InitialContext();
2101 ConnectionFactory factory = (QueueConnectionFactory) jndiCtx.lookup("java:/JmsXA");
2102 Queue queue = (Queue) jndiCtx.lookup("queue/gss-indexingQueue");
2103 qConn = factory.createConnection();
2104 session = qConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
2105 sender = session.createProducer(queue);
2107 for (Long id : fileIds) {
2108 MapMessage map = session.createMapMessage();
2109 map.setObject("id", id);
2110 map.setBoolean("delete", false);
2113 sendOptimize(httpClient, 0);
2114 } catch (DOMException e) {
2115 throw new EJBException(e);
2116 } catch (TransformerConfigurationException e) {
2117 throw new EJBException(e);
2118 } catch (IllegalArgumentException e) {
2119 throw new EJBException(e);
2120 } catch (HttpException e) {
2121 throw new EJBException(e);
2122 } catch (UnsupportedEncodingException e) {
2123 throw new EJBException(e);
2124 } catch (ParserConfigurationException e) {
2125 throw new EJBException(e);
2126 } catch (TransformerException e) {
2127 throw new EJBException(e);
2128 } catch (IOException e) {
2129 throw new EJBException(e);
2130 } catch (NamingException e) {
2131 throw new EJBException(e);
2132 } catch (JMSException e) {
2133 throw new EJBException(e);
2139 if (session != null)
2144 catch (JMSException e) {
2151 * Sends a optimize message to the solr server
2154 * @param retryCount If the commit fails, it is retried three times. This parameter is passed in the recursive
2155 * calls to stop the recursion
2156 * @throws UnsupportedEncodingException
2157 * @throws IOException
2158 * @throws HttpException
2160 private void sendOptimize(HttpClient httpClient, int retryCount) throws UnsupportedEncodingException, IOException, HttpException {
2161 PostMethod method = null;
2163 logger.debug("Optimize retry: " + retryCount);
2164 method = new PostMethod(getConfiguration().getString("solrUpdateUrl"));
2165 method.setRequestEntity(new StringRequestEntity("<optimize/>", "text/xml", "iso8859-1"));
2166 int statusCode = httpClient.executeMethod(method);
2167 logger.debug("HTTP status: " + statusCode);
2168 String response = method.getResponseBodyAsString();
2169 logger.debug(response);
2170 if (statusCode != 200 && retryCount < 2) {
2172 Thread.sleep(10000); //Give Solr a little time to be available
2173 } catch (InterruptedException e) {
2175 sendOptimize(httpClient, retryCount + 1);
2180 method.releaseConnection();
2184 public FileHeaderDTO createFile(Long userId, Long folderId, String name, String mimeType, long fileSize, String filePath)
2185 throws DuplicateNameException, ObjectNotFoundException, GSSIOException,
2186 InsufficientPermissionsException, QuotaExceededException {
2189 throw new ObjectNotFoundException("No user specified");
2190 if (folderId == null)
2191 throw new ObjectNotFoundException("No folder specified");
2192 String contentType = mimeType;
2193 if (StringUtils.isEmpty(mimeType))
2194 contentType = DEFAULT_MIME_TYPE;
2195 if (StringUtils.isEmpty(name))
2196 throw new ObjectNotFoundException("No file name specified");
2197 if (dao.existsFolderOrFile(folderId, name))
2198 throw new DuplicateNameException("A folder or file with the name '" + name +
2199 "' already exists at this level");
2201 // Do the actual work.
2202 Folder parent = null;
2204 parent = dao.getEntityById(Folder.class, folderId);
2205 } catch (final ObjectNotFoundException onfe) {
2206 // Supply a more accurate problem description.
2207 throw new ObjectNotFoundException("Parent folder not found");
2209 final User owner = dao.getEntityById(User.class, userId);
2210 if (!parent.hasWritePermission(owner))
2211 throw new InsufficientPermissionsException("You don't have the permissions to write to this folder");
2212 final FileHeader file = new FileHeader();
2214 parent.addFile(file);
2215 // set file owner to folder owner
2216 file.setOwner(parent.getOwner());
2218 final Date now = new Date();
2219 final AuditInfo auditInfo = new AuditInfo();
2220 auditInfo.setCreatedBy(owner);
2221 auditInfo.setCreationDate(now);
2222 auditInfo.setModifiedBy(owner);
2223 auditInfo.setModificationDate(now);
2224 file.setAuditInfo(auditInfo);
2225 // TODO set the proper versioning flag on creation
2226 file.setVersioned(false);
2228 for (final Permission p : parent.getPermissions()) {
2229 final Permission permission = new Permission();
2230 permission.setGroup(p.getGroup());
2231 permission.setUser(p.getUser());
2232 permission.setRead(p.getRead());
2233 permission.setWrite(p.getWrite());
2234 permission.setModifyACL(p.getModifyACL());
2235 file.addPermission(permission);
2238 // Create the file body.
2240 createFileBody(name, contentType, fileSize, filePath, file, auditInfo);
2241 } catch (FileNotFoundException e) {
2242 throw new GSSIOException(e);
2245 indexFile(file.getId(), false);
2247 return file.getDTO();
2251 * @see gr.ebs.gss.server.ejb.ExternalAPI#updateFileContents(java.lang.Long, java.lang.Long, java.lang.String, java.io.InputStream)
2253 public FileHeaderDTO updateFileContents(Long userId, Long fileId, String mimeType, long fileSize, String filePath) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
2255 throw new ObjectNotFoundException("No user specified");
2257 throw new ObjectNotFoundException("No file specified");
2258 String contentType = mimeType;
2260 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
2262 // if no mime type or the generic mime type is defined by the client, then try to identify it from the filename extension
2263 if (StringUtils.isEmpty(mimeType) || "application/octet-stream".equals(mimeType)
2264 || "application/download".equals(mimeType) || "application/force-download".equals(mimeType)
2265 || "octet/stream".equals(mimeType) || "application/unknown".equals(mimeType))
2266 contentType = identifyMimeType(file.getName());
2268 final User owner = dao.getEntityById(User.class, userId);
2269 if (!file.hasWritePermission(owner))
2270 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2271 final Date now = new Date();
2272 final AuditInfo auditInfo = new AuditInfo();
2273 auditInfo.setCreatedBy(owner);
2274 auditInfo.setCreationDate(now);
2275 auditInfo.setModifiedBy(owner);
2276 auditInfo.setModificationDate(now);
2278 createFileBody(file.getName(), contentType, fileSize, filePath, file, auditInfo);
2279 } catch (FileNotFoundException e) {
2280 throw new GSSIOException(e);
2283 indexFile(fileId, false);
2284 return file.getDTO();
2288 * Helper method for identifying mime type by examining the filename extension
2291 * @return the mime type
2293 private String identifyMimeType(String filename) {
2294 if (filename.indexOf('.') != -1) {
2295 String extension = filename.substring(filename.lastIndexOf('.')).toLowerCase(Locale.ENGLISH);
2296 if (".doc".equals(extension))
2297 return "application/msword";
2298 else if (".xls".equals(extension))
2299 return "application/vnd.ms-excel";
2300 else if (".ppt".equals(extension))
2301 return "application/vnd.ms-powerpoint";
2302 else if (".pdf".equals(extension))
2303 return "application/pdf";
2304 else if (".gif".equals(extension))
2306 else if (".jpg".equals(extension) || ".jpeg".equals(extension) || ".jpe".equals(extension))
2307 return "image/jpeg";
2308 else if (".tiff".equals(extension) || ".tif".equals(extension))
2309 return "image/tiff";
2310 else if (".png".equals(extension))
2312 else if (".bmp".equals(extension))
2315 // when all else fails assign the default mime type
2316 return DEFAULT_MIME_TYPE;
2320 * Helper method to create a new file body and attach it as the current body
2321 * of the provided file header.
2323 * @param name the original file name
2324 * @param mimeType the content type
2325 * @param fileSize the uploaded file size
2326 * @param filePath the uploaded file full path
2327 * @param header the file header that will be associated with the new body
2328 * @param auditInfo the audit info
2329 * @param owner the owner of the file
2330 * @throws FileNotFoundException
2331 * @throws QuotaExceededException
2333 private void createFileBody(String name, String mimeType, long fileSize, String filePath,
2334 FileHeader header, AuditInfo auditInfo)
2335 throws FileNotFoundException, QuotaExceededException {
2337 long currentTotalSize = 0;
2338 if (!header.isVersioned() && header.getCurrentBody() != null && header.getBodies() != null)
2339 currentTotalSize = header.getTotalSize();
2340 Long quotaLeft = getQuotaLeft(header.getOwner().getId());
2341 if(quotaLeft < fileSize-currentTotalSize) {
2342 // quota exceeded -> delete the file
2343 deleteActualFile(filePath);
2344 throw new QuotaExceededException("Not enough free space available");
2347 FileBody body = new FileBody();
2349 // if no mime type or the generic mime type is defined by the client, then try to identify it from the filename extension
2350 if (StringUtils.isEmpty(mimeType) || "application/octet-stream".equals(mimeType)
2351 || "application/download".equals(mimeType) || "application/force-download".equals(mimeType)
2352 || "octet/stream".equals(mimeType) || "application/unknown".equals(mimeType))
2353 body.setMimeType(identifyMimeType(name));
2355 body.setMimeType(mimeType);
2356 body.setAuditInfo(auditInfo);
2357 body.setFileSize(fileSize);
2358 body.setOriginalFilename(name);
2359 body.setStoredFilePath(filePath);
2360 //CLEAR OLD VERSION IF FILE IS NOT VERSIONED AND GETS UPDATED
2361 if(!header.isVersioned() && header.getCurrentBody() != null){
2362 header.setCurrentBody(null);
2363 if (header.getBodies() != null) {
2364 Iterator<FileBody> it = header.getBodies().iterator();
2365 while(it.hasNext()){
2366 FileBody bo = it.next();
2367 deleteActualFile(bo.getStoredFilePath());
2375 header.addBody(body);
2381 @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
2382 public File uploadFile(InputStream stream, Long userId) throws IOException, ObjectNotFoundException {
2384 throw new ObjectNotFoundException("No user specified");
2385 User owner = dao.getEntityById(User.class, userId);
2387 throw new ObjectNotFoundException("No user specified");
2388 long start = 0, end = 0;
2389 if (logger.isDebugEnabled())
2390 start = System.currentTimeMillis();
2391 File result = new File(generateRepositoryFilePath());
2393 final FileOutputStream output = new FileOutputStream(result);
2394 final byte[] buffer = new byte[UPLOAD_BUFFER_SIZE];
2397 while (-1 != (n = stream.read(buffer)))
2398 output.write(buffer, 0, n);
2401 } catch (IOException e) {
2402 if (!result.delete())
2403 logger.warn("Could not delete " + result.getPath());
2406 if (logger.isDebugEnabled()) {
2407 end = System.currentTimeMillis();
2408 logger.debug("Time to upload: " + (end - start) + " (msec)");
2414 public void createFileUploadProgress(Long userId, String filename, Long bytesTransfered, Long fileSize) throws ObjectNotFoundException{
2417 throw new ObjectNotFoundException("No user specified");
2418 User user = dao.getEntityById(User.class, userId);
2419 FileUploadStatus status = dao.getFileUploadStatus(userId, filename);
2421 status = new FileUploadStatus();
2422 status.setOwner(user);
2423 status.setFilename(filename);
2424 status.setBytesUploaded(bytesTransfered);
2425 status.setFileSize(fileSize);
2429 status.setBytesUploaded(bytesTransfered);
2430 status.setFileSize(fileSize);
2436 public void removeFileUploadProgress(Long userId, String filename) throws ObjectNotFoundException{
2438 throw new ObjectNotFoundException("No user specified");
2439 FileUploadStatus status = dao.getFileUploadStatus(userId, filename);
2445 public FileUploadStatus getFileUploadStatus(Long userId, String fileName) {
2446 return dao.getFileUploadStatus(userId, fileName);
2450 public FolderDTO getFolderWithSubfolders(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
2452 throw new ObjectNotFoundException("No user specified");
2453 if (folderId == null)
2454 throw new ObjectNotFoundException("No folder specified");
2455 final User user = dao.getEntityById(User.class, userId);
2456 final Folder folder = dao.getEntityById(Folder.class, folderId);
2457 // Check permissions
2458 if (!folder.hasReadPermission(user))
2459 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
2460 List<FolderDTO> subfolders = new ArrayList<FolderDTO>();
2461 if (folder.hasReadPermission(user))
2462 for (Folder f : folder.getSubfolders())
2463 if (f.hasReadPermission(user) && !f.isDeleted())
2464 subfolders.add(f.getDTO());
2465 FolderDTO result = folder.getDTO();
2466 result.setSubfolders(subfolders);
2467 return folder.getDTO();
2471 public FolderDTO getFolderWithSubfolders(Long userId, Long callingUserId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
2473 throw new ObjectNotFoundException("No user specified");
2474 if (folderId == null)
2475 throw new ObjectNotFoundException("No folder specified");
2476 User user = dao.getEntityById(User.class, callingUserId);
2477 Folder folder = dao.getEntityById(Folder.class, folderId);
2478 // Check permissions
2479 if (!folder.hasReadPermission(user))
2480 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
2482 FolderDTO result = folder.getDTO();
2483 result.setSubfolders(getSharedSubfolders(userId, callingUserId, folder.getId()));
2488 public FileBodyDTO getFileVersion(Long userId, Long fileId, int version)
2489 throws ObjectNotFoundException, InsufficientPermissionsException {
2491 throw new ObjectNotFoundException("No user specified");
2493 throw new ObjectNotFoundException("No file specified");
2495 throw new ObjectNotFoundException("No valid version specified");
2496 User user = dao.getEntityById(User.class, userId);
2497 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
2498 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
2499 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2500 FileBody body = dao.getFileVersion(fileId, version);
2501 return body.getDTO();
2505 public User updateUserPolicyAcceptance(Long userId, boolean isAccepted) throws ObjectNotFoundException {
2507 throw new ObjectNotFoundException("No user specified");
2508 User user = dao.getEntityById(User.class, userId);
2509 user.setAcceptedPolicy(isAccepted);
2514 public void updateAccounting(User user, Date date, long bandwidthDiff) {
2515 dao.updateAccounting(user, date, bandwidthDiff);
2519 public boolean canReadFolder(Long userId, Long folderId) throws ObjectNotFoundException {
2521 throw new ObjectNotFoundException("No user specified");
2522 if (folderId == null)
2523 throw new ObjectNotFoundException("No folder specified");
2524 User user = dao.getEntityById(User.class, userId);
2525 Folder folder = dao.getEntityById(Folder.class, folderId);
2526 // Check permissions
2527 if (!folder.hasReadPermission(user))
2533 * Reset WebDAV password for given user.
2536 * @return the new password
2537 * @throws ObjectNotFoundException
2540 public String resetWebDAVPassword(Long userId) throws ObjectNotFoundException {
2542 throw new ObjectNotFoundException("No user specified");
2543 User user = dao.getEntityById(User.class, userId);
2544 user.generateWebDAVPassword();
2545 return user.getWebDAVPassword();