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 void 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 createFolder(name, parent, creator);
298 * Create a new folder with the provided name, parent and owner.
304 private void createFolder(String name, Folder parent, User creator) {
305 Folder folder = new Folder();
306 folder.setName(name);
307 if (parent != null) {
308 parent.addSubfolder(folder);
309 folder.setOwner(parent.getOwner());
311 folder.setOwner(creator);
313 Date now = new Date();
314 AuditInfo auditInfo = new AuditInfo();
315 auditInfo.setCreatedBy(creator);
316 auditInfo.setCreationDate(now);
317 auditInfo.setModifiedBy(creator);
318 auditInfo.setModificationDate(now);
319 folder.setAuditInfo(auditInfo);
322 for (Permission p : parent.getPermissions()) {
323 Permission permission = new Permission();
324 permission.setGroup(p.getGroup());
325 permission.setUser(p.getUser());
326 permission.setRead(p.getRead());
327 permission.setWrite(p.getWrite());
328 permission.setModifyACL(p.getModifyACL());
329 folder.addPermission(permission);
332 Permission permission = new Permission();
333 permission.setUser(creator);
334 permission.setRead(true);
335 permission.setWrite(true);
336 permission.setModifyACL(true);
337 folder.addPermission(permission);
343 * Deletes the given folder and all its subfolders and files
344 * Only the permissions for top folder are checked
346 * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteFolder(java.lang.Long,
349 public void deleteFolder(final Long userId, final Long folderId) throws InsufficientPermissionsException, ObjectNotFoundException {
352 throw new ObjectNotFoundException("No user specified");
353 if (folderId == null)
354 throw new ObjectNotFoundException("No folder specified");
356 // Do the actual work.
357 final Folder folder = dao.getEntityById(Folder.class, folderId);
358 final Folder parent = folder.getParent();
360 throw new ObjectNotFoundException("Deleting the root folder is not allowed");
361 final User user = dao.getEntityById(User.class, userId);
362 if (!folder.hasDeletePermission(user)) {
363 logger.info("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
364 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
366 removeSubfolderFiles(folder);
367 parent.removeSubfolder(folder);
372 * Traverses the folder and deletes all actual files (file system)
373 * regardless of permissions
377 private void removeSubfolderFiles(Folder folder) {
378 //remove files for all subfolders
379 for (Folder subfolder:folder.getSubfolders())
380 removeSubfolderFiles(subfolder);
381 //remove this folder's file bodies (actual files)
382 for (FileHeader file:folder.getFiles()) {
383 for (FileBody body:file.getBodies())
384 deleteActualFile(body.getStoredFilePath());
385 indexFile(file.getId(), true);
389 @SuppressWarnings("unchecked")
390 public List<FolderDTO> getSubfolders(Long userId, Long folderId)
391 throws ObjectNotFoundException, InsufficientPermissionsException {
393 throw new ObjectNotFoundException("No user specified");
394 if (folderId == null)
395 throw new ObjectNotFoundException("No folder specified");
396 User user = dao.getEntityById(User.class, userId);
397 Folder folder = dao.getEntityById(Folder.class, folderId);
398 if (!folder.hasReadPermission(user))
399 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
400 List<FolderDTO> result = new ArrayList<FolderDTO>();
401 if (folder.hasReadPermission(user))
402 for (Folder f : folder.getSubfolders())
403 if (f.hasReadPermission(user) && !f.isDeleted())
404 result.add(f.getDTO());
409 public void modifyFolder(Long userId, Long folderId, String folderName)
410 throws InsufficientPermissionsException, ObjectNotFoundException, DuplicateNameException {
414 throw new ObjectNotFoundException("No user specified");
415 if (folderId == null)
416 throw new ObjectNotFoundException("No folder specified");
417 if (StringUtils.isEmpty(folderName))
418 throw new ObjectNotFoundException("New folder name is empty");
420 Folder folder = dao.getEntityById(Folder.class, folderId);
421 User user = dao.getEntityById(User.class, userId);
422 if (!folder.hasWritePermission(user))
423 throw new InsufficientPermissionsException("You don't have the necessary permissions");
425 Folder parent = folder.getParent();
427 if (!folder.getName().equals(folderName) && dao.existsFolderOrFile(parent.getId(), folderName))
428 throw new DuplicateNameException("A folder or file with the name '" + folderName + "' already exists at this level");
430 // Do the actual modification.
431 folder.setName(folderName);
438 * @see gr.ebs.gss.server.ejb.ExternalAPI#createGroup(java.lang.Long,
441 public void createGroup(final Long userId, final String name) throws ObjectNotFoundException, DuplicateNameException {
444 throw new ObjectNotFoundException("No user specified");
445 if (StringUtils.isEmpty(name))
446 throw new ObjectNotFoundException("New group name is empty");
447 if (dao.existsGroup(userId, name))
448 throw new DuplicateNameException("A group with the name '" + name + "' already exists");
450 // TODO: Check permissions
452 final User owner = dao.getEntityById(User.class, userId);
454 // Do the actual work.
455 owner.createGroup(name);
461 * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteGroup(java.lang.Long,
464 public void deleteGroup(final Long userId, final Long groupId) throws ObjectNotFoundException, InsufficientPermissionsException {
467 throw new ObjectNotFoundException("No user specified");
469 throw new ObjectNotFoundException("No group specified");
471 // Do the actual work.
472 final User owner = dao.getEntityById(User.class, userId);
473 final Group group = dao.getEntityById(Group.class, groupId);
474 // Only delete the group if actually owned by the user.
475 if (group.getOwner().equals(owner)) {
476 List<Folder> folders = dao.getFoldersPermittedForGroup(userId, groupId);
477 for (Folder f : folders){
478 f.getPermissions().removeAll(group.getPermissions());
479 for(FileHeader file : f.getFiles())
480 file.getPermissions().removeAll(group.getPermissions());
482 List<FileHeader> files = dao.getSharedFilesNotInSharedFolders(userId);
483 for(FileHeader h : files)
484 h.getPermissions().removeAll(group.getPermissions());
485 owner.removeSpecifiedGroup(group);
488 else throw new InsufficientPermissionsException("You are not the owner of this group");
492 public FileHeaderDTO createFile(Long userId, Long folderId, String name, String mimeType, InputStream stream)
493 throws DuplicateNameException, ObjectNotFoundException, GSSIOException,
494 InsufficientPermissionsException, QuotaExceededException {
497 file = uploadFile(stream, userId);
498 } catch ( IOException ioe) {
499 // Supply a more accurate problem description.
500 throw new GSSIOException("Problem creating file",ioe);
502 return createFile(userId, folderId, name, mimeType, file.length(), file.getAbsolutePath());
506 * @see gr.ebs.gss.server.ejb.ExternalAPIRemote#indexFile(java.lang.Long, boolean)
508 public void indexFile(Long fileId, boolean delete) {
509 Connection qConn = null;
510 Session session = null;
511 MessageProducer sender = null;
513 Context jndiCtx = new InitialContext();
514 ConnectionFactory factory = (QueueConnectionFactory) jndiCtx.lookup("java:/JmsXA");
515 Queue queue = (Queue) jndiCtx.lookup("queue/gss-indexingQueue");
516 qConn = factory.createConnection();
517 session = qConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
518 sender = session.createProducer(queue);
520 MapMessage map = session.createMapMessage();
521 map.setObject("id", fileId);
522 map.setBoolean("delete", delete);
525 catch (NamingException e) {
526 logger.error("Index was not updated: ", e);
528 catch (JMSException e) {
529 logger.error("Index was not updated: ", e);
540 catch (JMSException e) {
549 * A helper method that generates a unique file path for a stored file. The
550 * files are stored using random hash names that are distributed evenly in
551 * a 2-level tree of subdirectories named after the first two hex characters
552 * in the name. For example, file ab1234cd5769f will be stored in the path
553 * /file-repository-root/a/b/ab1234cd5769f. The directories will be created
554 * if they don't already exist.
556 * @return a unique new file path
558 private String generateRepositoryFilePath() {
559 String filename = Long.toHexString(random.nextLong());
560 String fileRepositoryPath = getConfiguration().getString("fileRepositoryPath","/tmp");
561 File root = new File(fileRepositoryPath);
564 File firstFolder = new File(root + File.separator + filename.substring(0, 1));
565 if (!firstFolder.exists())
567 File secondFolder = new File(firstFolder + File.separator + filename.substring(1, 2));
568 if (!secondFolder.exists())
569 secondFolder.mkdir();
570 return secondFolder + File.separator + filename;
576 * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteFile(java.lang.Long,
579 public void deleteFile(final Long userId, final Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
582 throw new ObjectNotFoundException("No user specified");
584 throw new ObjectNotFoundException("No file specified");
586 // Do the actual work.
587 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
588 final Folder parent = file.getFolder();
590 throw new ObjectNotFoundException("The specified file has no parent folder");
591 final User user = dao.getEntityById(User.class, userId);
592 if (!file.hasDeletePermission(user))
593 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
594 for (final FileBody body : file.getBodies())
595 deleteActualFile(body.getStoredFilePath());
597 indexFile(fileId, true);
600 private void deleteActualFile(String filePath) {
601 if (filePath == null)
603 File file = new File(filePath);
605 logger.error("Could not delete file " + filePath);
611 * @see gr.ebs.gss.server.ejb.ExternalAPI#createTag(java.lang.Long,
612 * java.lang.Long, java.lang.String)
614 public void createTag(final Long userId, final Long fileHeaderId, final String tag) throws ObjectNotFoundException {
616 throw new ObjectNotFoundException("No user specified");
617 if (fileHeaderId == null)
618 throw new ObjectNotFoundException("No file specified");
619 if (StringUtils.isEmpty(tag))
620 throw new ObjectNotFoundException("Tag is empty");
622 final User user = dao.getEntityById(User.class, userId);
623 final FileHeader fh = dao.getEntityById(FileHeader.class, fileHeaderId);
624 user.addTag(fh, tag);
628 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUserTags(java.lang.Long)
630 @WebMethod(operationName = "getUserTags")
631 public Set<String> getUserTags(final Long userId) throws ObjectNotFoundException {
632 return dao.getUserTags(userId);
636 * @see gr.ebs.gss.server.ejb.ExternalAPI#updateFile(java.lang.Long, java.lang.Long, java.lang.String, java.util.Set)
638 public void updateFile(Long userId, Long fileId, String name, String tagSet) throws ObjectNotFoundException, InsufficientPermissionsException {
640 throw new ObjectNotFoundException("No user specified");
642 throw new ObjectNotFoundException("No file specified");
643 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
644 User user = dao.getEntityById(User.class, userId);
645 if (!file.hasWritePermission(user))
646 throw new InsufficientPermissionsException("User " + user.getId() + " cannot update file " + file.getName() + "(" + file.getId() + ")");
650 List<FileTag> tags = file.getFileTags();
652 if (tagSet != null) {
653 Iterator<FileTag> i = tags.iterator();
654 while (i.hasNext()) {
655 FileTag tag = i.next();
662 StringTokenizer st = new StringTokenizer(tagSet, ",");
663 while (st.hasMoreTokens())
664 new FileTag(user, file, st.nextToken().trim());
667 // Re-index the file if it was modified.
668 if (name != null || tagSet != null)
669 indexFile(fileId, false);
673 public InputStream getFileContents(Long userId, Long fileId)
674 throws ObjectNotFoundException, InsufficientPermissionsException {
676 throw new ObjectNotFoundException("No user specified");
678 throw new ObjectNotFoundException("No file specified");
680 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
681 User user = dao.getEntityById(User.class, userId);
682 if (!header.hasReadPermission(user)) {
683 logger.info("User " + user.getId() + " cannot read file " + header.getName() + "(" + fileId + ")");
684 throw new InsufficientPermissionsException("You don't have the necessary permissions");
687 File f = new File(header.getCurrentBody().getStoredFilePath());
689 return new FileInputStream(f);
690 } catch (FileNotFoundException e) {
691 logger.error("Could not locate the contents of file " + f.getAbsolutePath());
692 throw new ObjectNotFoundException("The file contents could not be located");
697 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFileContents(java.lang.Long, java.lang.Long, java.lang.Long)
699 public InputStream getFileContents(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
701 throw new ObjectNotFoundException("No user specified");
703 throw new ObjectNotFoundException("No file specified");
705 throw new ObjectNotFoundException("No file specified");
707 final FileHeader header = dao.getEntityById(FileHeader.class, fileId);
708 final FileBody body = dao.getEntityById(FileBody.class, bodyId);
709 final User user = dao.getEntityById(User.class, userId);
710 if (!header.hasReadPermission(user)) {
711 logger.info("User " + user.getId() + " cannot read file " + header.getName() + "(" + fileId + ")");
712 throw new InsufficientPermissionsException("You don't have the necessary permissions");
715 File f = new File(body.getStoredFilePath());
717 return new FileInputStream(f);
718 } catch (FileNotFoundException e) {
719 logger.error("Could not locate the contents of file " + f.getAbsolutePath());
720 throw new ObjectNotFoundException("The file contents could not be located");
725 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFile(java.lang.Long, java.lang.Long)
727 public FileHeaderDTO getFile(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
729 throw new ObjectNotFoundException("No user specified");
731 throw new ObjectNotFoundException("No file specified");
732 final User user = dao.getEntityById(User.class, userId);
733 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
734 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
735 throw new InsufficientPermissionsException("You don't have the necessary permissions");
736 return file.getDTO();
740 public FileBodyDTO getFileBody(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
742 throw new ObjectNotFoundException("No user specified");
744 throw new ObjectNotFoundException("No file specified");
745 User user = dao.getEntityById(User.class, userId);
746 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
747 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
748 throw new InsufficientPermissionsException("You don't have the necessary permissions");
749 FileBody body = dao.getEntityById(FileBody.class, bodyId);
750 return body.getDTO();
754 public Object getResourceAtPath(Long ownerId, String path, boolean ignoreDeleted)
755 throws ObjectNotFoundException {
757 throw new ObjectNotFoundException("No user specified");
758 if (StringUtils.isEmpty(path))
759 throw new ObjectNotFoundException("No path specified");
761 User owner = dao.getEntityById(User.class, ownerId);
762 List<String> pathElements = new ArrayList<String>();
763 StringTokenizer st = new StringTokenizer(path, "/");
764 while (st.hasMoreTokens())
765 pathElements.add(st.nextToken());
766 if (pathElements.size() < 1)
767 return getRootFolder(owner.getId());
768 // Store the last element, since it requires special handling.
769 String lastElement = pathElements.remove(pathElements.size() - 1);
770 FolderDTO cursor = getRootFolder(owner.getId());
771 // Traverse and verify the specified folder path.
772 for (String pathElement : pathElements) {
773 cursor = getFolder(cursor.getId(), pathElement);
774 if (cursor.isDeleted())
775 throw new ObjectNotFoundException("Folder " + cursor.getPath() + " not found");
778 // Use the lastElement to retrieve the actual resource.
779 Object resource = null;
781 FileHeaderDTO file = getFile(cursor.getId(), lastElement);
782 if (ignoreDeleted && file.isDeleted())
783 throw new ObjectNotFoundException("Resource not found");
785 } catch (ObjectNotFoundException e) {
786 // Perhaps the requested resource is not a file, so
787 // check for folders as well.
788 FolderDTO folder = getFolder(cursor.getId(), lastElement);
789 if (ignoreDeleted && folder.isDeleted())
790 throw new ObjectNotFoundException("Resource not found");
797 * Retrieve a file for the specified user that has the specified name and
798 * its parent folder has id equal to folderId.
800 * @param userId the ID of the current user
801 * @param folderId the ID of the parent folder
802 * @param name the name of the requested file
803 * @return the file found
804 * @throws ObjectNotFoundException if the specified folder or file was not
805 * found, with the exception message mentioning the precise
808 private FileHeaderDTO getFile(Long folderId, String name) throws ObjectNotFoundException {
809 if (folderId == null)
810 throw new ObjectNotFoundException("No parent folder specified");
811 if (StringUtils.isEmpty(name))
812 throw new ObjectNotFoundException("No file specified");
814 FileHeader file = dao.getFile(folderId, name);
815 return file.getDTO();
819 * Retrieve a folder for the specified user that has the specified name and
820 * its parent folder has id equal to parentId.
822 * @param parentId the ID of the parent folder
823 * @param name the name of the requested folder
824 * @return the folder found
825 * @throws ObjectNotFoundException if the specified folder or parent was not
826 * found, with the exception message mentioning the precise
829 private FolderDTO getFolder(Long parentId, String name) throws ObjectNotFoundException {
830 if (parentId == null)
831 throw new ObjectNotFoundException("No parent folder specified");
832 if (StringUtils.isEmpty(name))
833 throw new ObjectNotFoundException("No folder specified");
835 Folder folder = dao.getFolder(parentId, name);
836 return folder.getDTO();
839 private FileHeaderDTO updateFileContents(Long userId, Long fileId, String mimeType, InputStream resourceInputStream) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
842 file = uploadFile(resourceInputStream, userId);
843 } catch ( IOException ioe) {
844 // Supply a more accurate problem description.
845 throw new GSSIOException("Problem creating file",ioe);
847 return updateFileContents(userId, fileId, mimeType, file.length(), file.getAbsolutePath());
851 public void copyFile(Long userId, Long fileId, String dest) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
853 throw new ObjectNotFoundException("No user specified");
855 throw new ObjectNotFoundException("No file specified");
856 if (StringUtils.isEmpty(dest))
857 throw new ObjectNotFoundException("No destination specified");
859 Object destination = getResourceAtPath(userId, getParentPath(dest), true);
860 if (!(destination instanceof FolderDTO))
861 throw new ObjectNotFoundException("Destination parent folder not found");
862 FolderDTO parent = (FolderDTO) destination;
863 copyFile(userId, fileId, parent.getId(), getLastElement(dest));
867 public void copyFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
869 throw new ObjectNotFoundException("No user specified");
871 throw new ObjectNotFoundException("No owner specified");
873 throw new ObjectNotFoundException("No file specified");
874 if (StringUtils.isEmpty(dest))
875 throw new ObjectNotFoundException("No destination specified");
877 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
878 if (!(destination instanceof FolderDTO))
879 throw new ObjectNotFoundException("Destination parent folder not found");
880 FolderDTO parent = (FolderDTO) destination;
881 copyFile(userId, fileId, parent.getId(), getLastElement(dest));
885 public void copyFile(Long userId, Long fileId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
887 throw new ObjectNotFoundException("No user specified");
889 throw new ObjectNotFoundException("No file specified");
891 throw new ObjectNotFoundException("No destination specified");
892 if (StringUtils.isEmpty(destName))
893 throw new ObjectNotFoundException("No destination file name specified");
895 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
896 Folder destination = dao.getEntityById(Folder.class, destId);
897 User user = dao.getEntityById(User.class, userId);
898 if (!file.hasReadPermission(user) || !destination.hasWritePermission(user))
899 throw new InsufficientPermissionsException("You don't have the necessary permissions");
900 boolean versioned = file.isVersioned();
901 int versionsNumber = file.getBodies().size();
902 FileBody oldestBody = file.getBodies().get(0);
903 assert oldestBody != null;
904 File contents = new File(oldestBody.getStoredFilePath());
906 createFile(user.getId(), destination.getId(), destName, oldestBody.getMimeType(), new FileInputStream(contents));
907 FileHeader copiedFile = dao.getFile(destination.getId(), destName);
908 copiedFile.setVersioned(versioned);
910 if (versionsNumber > 1)
911 for (int i = 1; i < versionsNumber; i++) {
912 FileBody body = file.getBodies().get(i);
914 contents = new File(body.getStoredFilePath());
915 updateFileContents(user.getId(), copiedFile.getId(), body.getMimeType(), new FileInputStream(contents));
917 List<FileTag> tags = file.getFileTags();
918 for (FileTag tag : tags)
919 createTag(userId, copiedFile.getId(), tag.getTag());
921 } catch (FileNotFoundException e) {
922 throw new ObjectNotFoundException("File contents not found for file " + contents.getAbsolutePath());
928 public void copyFolder(Long userId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
930 throw new ObjectNotFoundException("No user specified");
931 if (folderId == null)
932 throw new ObjectNotFoundException("No folder specified");
933 if (StringUtils.isEmpty(dest))
934 throw new ObjectNotFoundException("No destination specified");
936 Object destination = getResourceAtPath(userId, getParentPath(dest), true);
937 if (!(destination instanceof FolderDTO))
938 throw new ObjectNotFoundException("Destination folder not found");
939 FolderDTO parent = (FolderDTO) destination;
940 copyFolder(userId, folderId, parent.getId(), getLastElement(dest));
944 public void copyFolder(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
946 throw new ObjectNotFoundException("No user specified");
947 if (folderId == null)
948 throw new ObjectNotFoundException("No folder specified");
950 throw new ObjectNotFoundException("No destination specified");
951 if (StringUtils.isEmpty(destName))
952 throw new ObjectNotFoundException("No destination folder name specified");
953 Folder folder = dao.getEntityById(Folder.class, folderId);
954 Folder destination = dao.getEntityById(Folder.class, destId);
955 User user = dao.getEntityById(User.class, userId);
956 if (!destination.hasWritePermission(user) || !folder.hasReadPermission(user))
957 throw new InsufficientPermissionsException("You don't have the necessary permissions");
958 createFolder(user.getId(), destination.getId(), destName);
962 public void copyFolderStructureToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
964 throw new ObjectNotFoundException("No user specified");
966 throw new ObjectNotFoundException("No owner specified");
967 if (folderId == null)
968 throw new ObjectNotFoundException("No folder specified");
969 if (StringUtils.isEmpty(dest))
970 throw new ObjectNotFoundException("No destination specified");
972 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
973 if (!(destination instanceof FolderDTO))
974 throw new ObjectNotFoundException("Destination folder not found");
975 FolderDTO parent = (FolderDTO) destination;
976 copyFolderStructure(userId, folderId, parent.getId(), getLastElement(dest));
980 public void copyFolderStructure(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
982 throw new ObjectNotFoundException("No user specified");
983 if (folderId == null)
984 throw new ObjectNotFoundException("No folder specified");
986 throw new ObjectNotFoundException("No destination specified");
987 if (StringUtils.isEmpty(destName))
988 throw new ObjectNotFoundException("No destination folder name specified");
990 Folder folder = dao.getEntityById(Folder.class, folderId);
991 Folder destination = dao.getEntityById(Folder.class, destId);
992 final User user = dao.getEntityById(User.class, userId);
993 // XXX: quick fix need to copy only visible items to user (Source
995 if (!folder.getOwner().getId().equals(userId) && !folder.hasReadPermission(user))
997 if(folder.isDeleted())//do not copy trashed folder and contents
999 if (!destination.hasWritePermission(user) || !folder.hasReadPermission(user))
1000 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1001 createFolder(user.getId(), destination.getId(), destName);
1002 Folder createdFolder = dao.getFolder(destination.getId(), destName);
1003 List<FileHeader> files = folder.getFiles();
1005 for (FileHeader file : files)
1006 if(!file.isDeleted())
1007 copyFile(userId, file.getId(), createdFolder.getId(), file.getName());
1008 List<Folder> subFolders = folder.getSubfolders();
1009 if (subFolders != null)
1010 for (Folder sub : subFolders)
1011 if(!sub.getId().equals(createdFolder.getId()))
1012 copyFolderStructure(userId, sub.getId(), createdFolder.getId(), sub.getName());
1017 * For a provided path, remove the last element and return the rest, that is
1018 * the path of the parent folder.
1020 * @param path the specified path
1021 * @return the path of the parent folder
1022 * @throws ObjectNotFoundException if the provided string contains no path
1025 private String getParentPath(String path) throws ObjectNotFoundException {
1026 int lastDelimiter = path.lastIndexOf('/');
1027 if (lastDelimiter == 0)
1029 if (lastDelimiter == -1)
1031 throw new ObjectNotFoundException("There is no parent in the path: " + path);
1032 else if (lastDelimiter < path.length() - 1)
1033 // Return the part before the delimiter.
1034 return path.substring(0, lastDelimiter);
1036 // Remove the trailing delimiter and then recurse.
1037 String strippedTrail = path.substring(0, lastDelimiter);
1038 return getParentPath(strippedTrail);
1043 * Get the last element in a path that denotes the file or folder name.
1045 * @param path the provided path
1046 * @return the last element in the path
1048 private String getLastElement(String path) {
1049 int lastDelimiter = path.lastIndexOf('/');
1050 if (lastDelimiter == -1)
1053 else if (lastDelimiter < path.length() - 1)
1054 // Return the part after the delimiter.
1055 return path.substring(lastDelimiter + 1);
1057 // Remove the trailing delimiter and then recurse.
1058 String strippedTrail = path.substring(0, lastDelimiter);
1059 return getLastElement(strippedTrail);
1064 public void moveFileToTrash(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1066 throw new ObjectNotFoundException("No user specified");
1068 throw new ObjectNotFoundException("No file specified");
1070 // Do the actual work.
1071 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1072 Folder parent = file.getFolder();
1074 throw new ObjectNotFoundException("The specified file has no parent folder");
1075 User user = dao.getEntityById(User.class, userId);
1076 if (!file.hasDeletePermission(user))
1077 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
1079 file.setDeleted(true);
1084 public void moveFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, InsufficientPermissionsException, QuotaExceededException {
1086 throw new ObjectNotFoundException("No user specified");
1087 if (ownerId == null)
1088 throw new ObjectNotFoundException("No owner specified");
1090 throw new ObjectNotFoundException("No file specified");
1091 if (StringUtils.isEmpty(dest))
1092 throw new ObjectNotFoundException("No destination specified");
1094 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1095 if (!(destination instanceof FolderDTO))
1096 throw new ObjectNotFoundException("Destination parent folder not found");
1097 FolderDTO parent = (FolderDTO) destination;
1098 moveFile(userId, fileId, parent.getId(), getLastElement(dest));
1102 public void moveFile(Long userId, Long fileId, Long destId, String destName) throws InsufficientPermissionsException, ObjectNotFoundException, QuotaExceededException {
1104 throw new ObjectNotFoundException("No user specified");
1106 throw new ObjectNotFoundException("No file specified");
1108 throw new ObjectNotFoundException("No destination specified");
1109 if (StringUtils.isEmpty(destName))
1110 throw new ObjectNotFoundException("No destination file name specified");
1112 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1113 Folder destination = dao.getEntityById(Folder.class, destId);
1115 User owner = dao.getEntityById(User.class, userId);
1116 if (!file.hasDeletePermission(owner) || !destination.hasWritePermission(owner))
1117 throw new InsufficientPermissionsException("User " + owner.getId() + " cannot move file " + file.getName() + "(" + file.getId() + ")");
1119 // if the destination folder belongs to another user:
1120 if (!file.getOwner().equals(destination.getOwner())) {
1121 // (a) check if the destination quota allows the move
1122 if(getQuotaLeft(destination.getOwner().getId()) < file.getTotalSize())
1123 throw new QuotaExceededException("Not enough free space available");
1124 User newOwner = destination.getOwner();
1125 // (b) if quota OK, change the owner of the file
1126 file.setOwner(newOwner);
1127 // if the file has no permission for the new owner, add it
1128 Permission ownerPermission = null;
1129 for (final Permission p : file.getPermissions())
1130 if (p.getUser() != null)
1131 if (p.getUser().equals(newOwner)) {
1132 ownerPermission = p;
1135 if (ownerPermission == null) {
1136 ownerPermission = new Permission();
1137 ownerPermission.setUser(newOwner);
1138 file.addPermission(ownerPermission);
1140 ownerPermission.setRead(true);
1141 ownerPermission.setWrite(true);
1142 ownerPermission.setModifyACL(true);
1144 // move the file to the destination folder
1145 file.setFolder(destination);
1149 public void moveFolderToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1151 throw new ObjectNotFoundException("No user specified");
1152 if (ownerId == null)
1153 throw new ObjectNotFoundException("No owner specified");
1154 if (folderId == null)
1155 throw new ObjectNotFoundException("No folder specified");
1156 if (StringUtils.isEmpty(dest))
1157 throw new ObjectNotFoundException("No destination specified");
1159 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1160 if (!(destination instanceof FolderDTO))
1161 throw new ObjectNotFoundException("Destination parent folder not found");
1162 FolderDTO parent = (FolderDTO) destination;
1163 moveFolder(userId, folderId, parent.getId(), getLastElement(dest));
1167 public void moveFolder(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1168 // TODO Simple Move and delete of original folder, in production
1169 // scenario we must first check individual files and folders permissions
1170 copyFolderStructure(userId, folderId, destId, destName);
1171 deleteFolder(userId, folderId);
1175 * @see gr.ebs.gss.server.ejb.ExternalAPI#getDeletedFiles(java.lang.Long)
1177 public List<FileHeaderDTO> getDeletedFiles(Long userId) throws ObjectNotFoundException {
1180 throw new ObjectNotFoundException("No user specified");
1182 // Do the actual work.
1183 final List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1184 final List<FileHeader> files = dao.getDeletedFiles(userId);
1185 for (final FileHeader f : files)
1186 result.add(f.getDTO());
1191 public void removeFileFromTrash(Long userId, Long fileId)
1192 throws ObjectNotFoundException, InsufficientPermissionsException {
1194 throw new ObjectNotFoundException("No user specified");
1196 throw new ObjectNotFoundException("No file specified");
1198 // Do the actual work.
1199 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1200 Folder parent = file.getFolder();
1202 throw new ObjectNotFoundException("The specified file has no parent folder");
1203 User user = dao.getEntityById(User.class, userId);
1204 if (!file.hasDeletePermission(user))
1205 throw new InsufficientPermissionsException("User " + user.getUsername() +
1206 " cannot restore file " + file.getName());
1208 file.setDeleted(false);
1213 public void moveFolderToTrash(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
1215 throw new ObjectNotFoundException("No user specified");
1216 if (folderId == null)
1217 throw new ObjectNotFoundException("No folder specified");
1218 Folder folder = dao.getEntityById(Folder.class, folderId);
1219 User user = dao.getEntityById(User.class, userId);
1220 if (!folder.hasDeletePermission(user))
1221 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1222 folder.setDeleted(true);
1224 for (FileHeader file : folder.getFiles())
1225 moveFileToTrash(userId, file.getId());
1226 for (Folder subFolder : folder.getSubfolders())
1227 moveFolderToTrash(userId, subFolder.getId());
1232 public void removeFolderFromTrash(Long userId, Long folderId)
1233 throws ObjectNotFoundException, InsufficientPermissionsException {
1235 throw new ObjectNotFoundException("No user specified");
1236 if (folderId == null)
1237 throw new ObjectNotFoundException("No folder specified");
1238 Folder folder = dao.getEntityById(Folder.class, folderId);
1239 User user = dao.getEntityById(User.class, userId);
1240 if (!folder.hasDeletePermission(user))
1241 throw new InsufficientPermissionsException("User " + user.getUsername() +
1242 " cannot restore folder " + folder.getName());
1243 folder.setDeleted(false);
1244 for (FileHeader file : folder.getFiles())
1245 removeFileFromTrash(userId, file.getId());
1246 for (Folder subFolder : folder.getSubfolders())
1247 removeFolderFromTrash(userId, subFolder.getId());
1252 public List<FolderDTO> getDeletedRootFolders(Long userId) throws ObjectNotFoundException {
1253 List<Folder> folders = dao.getDeletedRootFolders(userId);
1254 List<FolderDTO> result = new ArrayList<FolderDTO>();
1255 for (Folder folder : folders)
1256 result.add(folder.getDTO());
1261 public void emptyTrash(Long userId) throws ObjectNotFoundException, InsufficientPermissionsException {
1262 List<FolderDTO> deletedRootFolders = getDeletedRootFolders(userId);
1263 for (FolderDTO fdto : deletedRootFolders)
1264 deleteFolder(userId, fdto.getId());
1265 List<FileHeaderDTO> deletedFiles = getDeletedFiles(userId);
1266 for (FileHeaderDTO filedto : deletedFiles)
1267 deleteFile(userId, filedto.getId());
1271 public void restoreTrash(Long userId) throws ObjectNotFoundException, InsufficientPermissionsException {
1272 List<FolderDTO> deletedRootFolders = getDeletedRootFolders(userId);
1273 for (FolderDTO fdto : deletedRootFolders)
1274 removeFolderFromTrash(userId, fdto.getId());
1275 List<FileHeaderDTO> deletedFiles = getDeletedFiles(userId);
1276 for (FileHeaderDTO filedto : deletedFiles)
1277 removeFileFromTrash(userId, filedto.getId());
1281 public User createUser(String username, String name, String mail) throws ObjectNotFoundException {
1282 if (username == null)
1283 throw new ObjectNotFoundException("No username specified");
1285 throw new ObjectNotFoundException("No name specified");
1287 User user = new User();
1288 user.setUsername(username);
1290 user.setEmail(mail);
1291 Date now = new Date();
1292 AuditInfo auditInfo = new AuditInfo();
1293 auditInfo.setCreationDate(now);
1294 auditInfo.setModificationDate(now);
1295 user.setAuditInfo(auditInfo);
1296 user.generateAuthToken();
1297 user.generateWebDAVPassword();
1299 // Make sure we get an ID in the user object.
1301 // Create the root folder for the user.
1302 createFolder(user.getName(), null, user);
1307 public User findUserByEmail(String email) {
1308 return dao.findUserByEmail(email);
1312 public void updateUser(User user) {
1317 public User updateUser(String username, String name, String mail) throws ObjectNotFoundException {
1318 if (username == null)
1319 throw new ObjectNotFoundException("No username specified");
1321 User user = dao.getUser(username);
1323 user.setEmail(mail);
1328 public User findUser(String username) {
1329 if (username == null)
1331 return dao.findUser(username);
1335 public User updateUserToken(Long userId) throws ObjectNotFoundException {
1337 throw new ObjectNotFoundException("No user specified");
1338 User user = dao.getEntityById(User.class, userId);
1339 user.generateAuthToken();
1344 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFolderPermissions(java.lang.Long, java.lang.Long)
1347 public Set<PermissionDTO> getFolderPermissions(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
1349 throw new ObjectNotFoundException("No user specified");
1350 if (folderId == null)
1351 throw new ObjectNotFoundException("No folder specified");
1352 User user = dao.getEntityById(User.class, userId);
1353 Folder folder = dao.getEntityById(Folder.class, folderId);
1354 if(!folder.hasReadPermission(user))
1355 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1356 Set<Permission> perms = folder.getPermissions();
1357 Set<PermissionDTO> result = new LinkedHashSet<PermissionDTO>();
1358 for (Permission perm : perms)
1359 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId()))
1360 result.add(perm.getDTO());
1361 for (Permission perm : perms)
1362 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId())) {
1364 result.add(perm.getDTO());
1370 * @see gr.ebs.gss.server.ejb.ExternalAPI#setFolderPermissions(java.lang.Long, java.lang.Long, java.util.Set)
1373 public void setFolderPermissions(Long userId, Long folderId, Set<PermissionDTO> permissions) throws ObjectNotFoundException, InsufficientPermissionsException {
1375 throw new ObjectNotFoundException("No user specified");
1376 if (folderId == null)
1377 throw new ObjectNotFoundException("No folder specified");
1378 User user = dao.getEntityById(User.class, userId);
1379 Folder folder = dao.getEntityById(Folder.class, folderId);
1380 if(!folder.hasModifyACLPermission(user))
1381 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1382 // Delete previous entries
1383 for (Permission perm: folder.getPermissions())
1385 folder.getPermissions().clear();
1386 for (PermissionDTO dto : permissions) {
1387 if (dto.getUser()!=null && dto.getUser().getId().equals(folder.getOwner().getId()) && (!dto.hasRead() || !dto.hasWrite() || !dto.hasModifyACL()))
1388 throw new InsufficientPermissionsException("Can't remove permissions from owner");
1389 // Don't include 'empty' permission
1390 if (!dto.getRead() && !dto.getWrite() && !dto.getModifyACL()) continue;
1391 folder.addPermission(getPermission(dto));
1394 for (FileHeader fh : folder.getFiles())
1395 setFilePermissions(userId, fh.getId(), fh.isReadForAll(), permissions);
1396 for (Folder sub : folder.getSubfolders())
1397 setFolderPermissions(userId, sub.getId(), permissions);
1400 private Permission getPermission(PermissionDTO dto) throws ObjectNotFoundException {
1401 Permission res = new Permission();
1402 if (dto.getGroup() != null)
1403 res.setGroup(dao.getEntityById(Group.class, dto.getGroup().getId()));
1404 else if (dto.getUser() != null)
1405 if (dto.getUser().getId() == null)
1406 res.setUser(dao.getUser(dto.getUser().getUsername()));
1408 res.setUser(dao.getEntityById(User.class, dto.getUser().getId()));
1409 res.setRead(dto.hasRead());
1410 res.setWrite(dto.hasWrite());
1411 res.setModifyACL(dto.hasModifyACL());
1416 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsersByUserNameLike(java.lang.String)
1419 public List<UserDTO> getUsersByUserNameLike(String username) {
1420 List<User> users = dao.getUsersByUserNameLike(username);
1421 List<UserDTO> result = new ArrayList<UserDTO>();
1422 for (User u : users)
1423 result.add(u.getDTO());
1429 * @see gr.ebs.gss.server.ejb.ExternalAPI#addUserToGroup(java.lang.Long, java.lang.Long, java.lang.Long)
1432 public void addUserToGroup(Long userId, Long groupId, Long userToAddId) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
1434 throw new ObjectNotFoundException("No user specified");
1435 if (groupId == null)
1436 throw new ObjectNotFoundException("No group specified");
1437 if (userToAddId == null)
1438 throw new ObjectNotFoundException("No user to add specified");
1439 User user = dao.getEntityById(User.class, userId);
1440 Group group = dao.getEntityById(Group.class, groupId);
1441 if (!group.getOwner().equals(user))
1442 throw new InsufficientPermissionsException();
1443 User userToAdd = dao.getEntityById(User.class, userToAddId);
1444 if (group.contains(userToAdd))
1445 throw new DuplicateNameException("User already exists in group");
1446 group.getMembers().add(userToAdd);
1452 public void invalidateUserToken(Long userId) throws ObjectNotFoundException {
1454 throw new ObjectNotFoundException("No user specified");
1455 User user = dao.getEntityById(User.class, userId);
1456 user.invalidateAuthToken();
1461 public List<FolderDTO> getSharedRootFolders(Long userId) throws ObjectNotFoundException {
1463 throw new ObjectNotFoundException("No user specified");
1464 List<Folder> folders = dao.getSharedRootFolders(userId);
1465 List<FolderDTO> result = new ArrayList<FolderDTO>();
1466 for (Folder f : folders) {
1467 FolderDTO dto = f.getDTO();
1468 dto.setSubfolders(getSharedSubfolders(userId, f.getId()));
1475 * @see gr.ebs.gss.server.ejb.ExternalAPI#removeMemberFromGroup(java.lang.Long, java.lang.Long, java.lang.Long)
1478 public void removeMemberFromGroup(Long userId, Long groupId, Long memberId) throws ObjectNotFoundException, InsufficientPermissionsException {
1480 throw new ObjectNotFoundException("No user specified");
1481 if (groupId == null)
1482 throw new ObjectNotFoundException("No group specified");
1483 if (memberId == null)
1484 throw new ObjectNotFoundException("No member specified");
1485 User owner = dao.getEntityById(User.class, userId);
1486 Group group = dao.getEntityById(Group.class, groupId);
1487 User member = dao.getEntityById(User.class, memberId);
1488 if (!group.getOwner().equals(owner))
1489 throw new InsufficientPermissionsException("User is not the owner of the group");
1490 group.removeMemberFromGroup(member);
1496 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsersSharingFoldersForUser(java.lang.Long)
1499 public List<UserDTO> getUsersSharingFoldersForUser(Long userId) throws ObjectNotFoundException {
1500 List<User> users = dao.getUsersSharingFoldersForUser(userId);
1501 List<User> usersFiles = dao.getUsersSharingFilesForUser(userId);
1502 List<UserDTO> res = new ArrayList<UserDTO>();
1503 for (User u : users)
1504 res.add(u.getDTO());
1505 for(User fu : usersFiles)
1506 if(!users.contains(fu))
1507 res.add(fu.getDTO());
1512 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFilePermissions(java.lang.Long, java.lang.Long)
1515 public Set<PermissionDTO> getFilePermissions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1517 throw new ObjectNotFoundException("No user specified");
1519 throw new ObjectNotFoundException("No folder specified");
1520 User user = dao.getEntityById(User.class, userId);
1521 FileHeader folder = dao.getEntityById(FileHeader.class, fileId);
1522 if(!folder.hasReadPermission(user))
1523 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1524 Set<Permission> perms = folder.getPermissions();
1525 Set<PermissionDTO> result = new LinkedHashSet<PermissionDTO>();
1526 for (Permission perm : perms)
1527 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId()))
1528 result.add(perm.getDTO());
1529 for (Permission perm : perms)
1530 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId())) {
1532 result.add(perm.getDTO());
1537 public void setFilePermissions(Long userId, Long fileId, Boolean readForAll, Set<PermissionDTO> permissions) throws ObjectNotFoundException, InsufficientPermissionsException {
1539 throw new ObjectNotFoundException("No user specified");
1541 throw new ObjectNotFoundException("No folder specified");
1543 User user = dao.getEntityById(User.class, userId);
1544 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1545 if(!file.hasModifyACLPermission(user))
1546 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1548 if (readForAll != null)
1549 if (user.equals(file.getOwner()))
1550 file.setReadForAll(readForAll);
1552 throw new InsufficientPermissionsException("Only the owner can change the read-for-all flag");
1554 // Update the file if there was a change.
1555 if (readForAll != null || permissions != null && !permissions.isEmpty()) {
1556 if (permissions != null && !permissions.isEmpty()) {
1557 // Delete previous entries
1558 for (Permission perm: file.getPermissions())
1560 file.getPermissions().clear();
1561 for (PermissionDTO dto : permissions) {
1562 if (dto.getUser()!=null && dto.getUser().getId().equals(file.getOwner().getId()) && (!dto.hasRead() || !dto.hasWrite() || !dto.hasModifyACL()))
1563 throw new InsufficientPermissionsException("Can't remove permissions from owner");
1564 // Don't include 'empty' permission
1565 if (!dto.getRead() && !dto.getWrite() && !dto.getModifyACL()) continue;
1566 file.addPermission(getPermission(dto));
1575 public List<FileHeaderDTO> getSharedFilesNotInSharedFolders(Long userId) throws ObjectNotFoundException {
1577 throw new ObjectNotFoundException("No user specified");
1578 List<FileHeader> files = dao.getSharedFilesNotInSharedFolders(userId);
1579 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1580 for (FileHeader f : files)
1581 result.add(f.getDTO());
1586 public List<FileHeaderDTO> getSharedFiles(Long userId) throws ObjectNotFoundException {
1588 throw new ObjectNotFoundException("No user specified");
1589 List<FileHeader> files = dao.getSharedFiles(userId);
1590 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1591 for (FileHeader f : files)
1592 result.add(f.getDTO());
1597 public List<FolderDTO> getSharedFolders(Long userId) throws ObjectNotFoundException {
1599 throw new ObjectNotFoundException("No user specified");
1600 List<Folder> folders = dao.getSharedFolders(userId);
1601 List<FolderDTO> result = new ArrayList<FolderDTO>();
1602 for (Folder f : folders)
1603 result.add(f.getDTO());
1608 * @see gr.ebs.gss.server.ejb.ExternalAPI#getSharedFiles(java.lang.Long, java.lang.Long)
1611 public List<FileHeaderDTO> getSharedFiles(Long ownerId, Long callingUserId) throws ObjectNotFoundException {
1612 if (ownerId == null)
1613 throw new ObjectNotFoundException("No owner specified");
1614 if (callingUserId == null)
1615 throw new ObjectNotFoundException("No calling user specified");
1616 List<FileHeader> folders = dao.getSharedFiles(ownerId, callingUserId);
1617 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1618 for (FileHeader f : folders)
1619 result.add(f.getDTO());
1624 public List<FolderDTO> getSharedRootFolders(Long ownerId, Long callingUserId) throws ObjectNotFoundException {
1625 if (ownerId == null)
1626 throw new ObjectNotFoundException("No owner specified");
1627 if (callingUserId == null)
1628 throw new ObjectNotFoundException("No calling user specified");
1629 List<Folder> folders = dao.getSharedRootFolders(ownerId, callingUserId);
1630 List<FolderDTO> result = new ArrayList<FolderDTO>();
1631 for (Folder f : folders) {
1632 FolderDTO dto = f.getDTO();
1633 dto.setSubfolders(getSharedSubfolders(ownerId, callingUserId, f.getId()));
1641 public List<FolderDTO> getSharedSubfolders(Long userId, Long folderId) throws ObjectNotFoundException {
1643 throw new ObjectNotFoundException("No user specified");
1644 if (folderId == null)
1645 throw new ObjectNotFoundException("No folder specified");
1646 User user = dao.getEntityById(User.class, userId);
1647 Folder folder = dao.getEntityById(Folder.class, folderId);
1648 List<FolderDTO> result = new ArrayList<FolderDTO>();
1649 if (folder.isShared(user))
1650 for (Folder f : folder.getSubfolders())
1651 if (f.isShared(user) && !f.isDeleted())
1652 result.add(f.getDTO());
1657 public List<FolderDTO> getSharedSubfolders(Long userId, Long callingUserId, Long folderId) throws ObjectNotFoundException {
1659 throw new ObjectNotFoundException("No user specified");
1660 if (callingUserId == null)
1661 throw new ObjectNotFoundException("No user specified");
1662 if (folderId == null)
1663 throw new ObjectNotFoundException("No folder specified");
1664 User user = dao.getEntityById(User.class, callingUserId);
1665 Folder folder = dao.getEntityById(Folder.class, folderId);
1666 List<FolderDTO> result = new ArrayList<FolderDTO>();
1667 if (folder.isSharedForOtherUser(user))
1668 for (Folder f : folder.getSubfolders())
1669 if (f.isSharedForOtherUser(user) && !f.isDeleted()){
1670 FolderDTO dto = f.getDTO();
1671 dto.setSubfolders(getSharedSubfolders(userId, callingUserId, dto.getId()));
1679 * @see gr.ebs.gss.server.ejb.ExternalAPI#searchFiles(java.lang.Long, java.lang.String)
1682 public List<FileHeaderDTO> searchFiles(Long userId, String query) throws ObjectNotFoundException {
1684 throw new ObjectNotFoundException("No user specified");
1685 User user = getUser(userId);
1687 throw new ObjectNotFoundException("No query specified");
1688 List<FileHeader> files = search(user.getId(), query);
1689 List<FileHeaderDTO> res = new ArrayList<FileHeaderDTO>();
1690 for(FileHeader f : files)
1691 res.add(f.getDTO());
1696 * Performs the actuals search on the solr server and returns the results
1698 * We have to use the dismax query type (instead of the
1699 * standard) because it allows for search time field boosting. This is because we can't use indexing
1700 * time field boosting due to the patched rich indexing API that does not allow it
1704 * @return a List of FileHeader objects
1706 private List<FileHeader> search(Long userId, String query) {
1708 HttpClient httpClient = new HttpClient();
1710 GetMethod method = new GetMethod(getConfiguration().getString("solrSelectUrl"));
1711 NameValuePair[] params = {new NameValuePair("qt", "dismax"),
1712 new NameValuePair("q", query),
1713 new NameValuePair("sort", "score desc"),
1714 new NameValuePair("indent", "on")};
1715 method.setQueryString(params);
1718 String response = null;
1720 statusCode = httpClient.executeMethod(method);
1721 logger.debug("HTTP status: " + statusCode);
1722 response = method.getResponseBodyAsString();
1723 logger.debug(response);
1725 if (statusCode != 200 && retryCount < 3)
1727 Thread.sleep(3000); //Give Solr a little time to be available
1728 } catch (InterruptedException e) {
1730 } while (statusCode != 200 && retryCount < 3);
1731 if (statusCode != 200)
1732 throw new EJBException("Search query return error:\n" + response);
1734 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
1735 DocumentBuilder db = dbf.newDocumentBuilder();
1736 Document doc = db.parse(method.getResponseBodyAsStream());
1737 method.releaseConnection();
1739 Node root = doc.getElementsByTagName("response").item(0);
1740 Node lst = root.getFirstChild().getNextSibling();
1741 Node status = lst.getFirstChild().getNextSibling();
1742 if (status.getAttributes().getNamedItem("name").getNodeValue().equals("status") &&
1743 status.getTextContent().equals("0")) {
1744 List<FileHeader> fileResult = new ArrayList<FileHeader>();
1745 Node result = lst.getNextSibling().getNextSibling();
1746 NodeList docs = result.getChildNodes();
1747 User user = getUser(userId);
1748 for (int i=1; i<docs.getLength(); i=i+2) {
1749 Node d = docs.item(i);
1750 NodeList docData = d.getChildNodes();
1751 for (int j=1; j<docData.getLength(); j=j+2) {
1752 Node dd = docData.item(j);
1753 if (dd.getAttributes().item(0).getNodeName().equals("name") &&
1754 dd.getAttributes().item(0).getNodeValue().equals("id")) {
1755 Long fileId = Long.valueOf(dd.getTextContent());
1757 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1758 if (file.hasReadPermission(user)) {
1759 fileResult.add(file);
1760 logger.debug("File added " + fileId);
1762 } catch (ObjectNotFoundException e) {
1763 logger.warn("Search result not found", e);
1770 throw new EJBException();
1771 } catch (HttpException e) {
1772 throw new EJBException(e);
1773 } catch (IOException e) {
1774 throw new EJBException(e);
1775 } catch (SAXException e) {
1776 throw new EJBException(e);
1777 } catch (ParserConfigurationException e) {
1778 throw new EJBException(e);
1779 } catch (ObjectNotFoundException e) {
1780 throw new EJBException(e);
1785 * @see gr.ebs.gss.server.ejb.ExternalAPI#copyFiles(java.lang.Long, java.util.List, java.lang.Long)
1788 public void copyFiles(Long userId, List<Long> fileIds, Long destId) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
1789 for(Long l : fileIds){
1790 FileHeader file = dao.getEntityById(FileHeader.class, l);
1791 copyFile(userId, l, destId, file.getName());
1798 * @see gr.ebs.gss.server.ejb.ExternalAPI#moveFiles(java.lang.Long, java.util.List, java.lang.Long)
1801 public void moveFiles(Long userId, List<Long> fileIds, Long destId) throws InsufficientPermissionsException, ObjectNotFoundException, QuotaExceededException {
1802 for(Long l : fileIds){
1803 FileHeader file = dao.getEntityById(FileHeader.class, l);
1804 moveFile(userId, l, destId, file.getName());
1810 * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteFiles(java.lang.Long, java.util.List)
1813 public void deleteFiles(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1815 throw new ObjectNotFoundException("No user specified");
1816 final User user = dao.getEntityById(User.class, userId);
1817 List<String> filesToRemove = new ArrayList<String>();
1818 //first delete database objects
1819 for(Long fileId : fileIds){
1821 throw new ObjectNotFoundException("No file specified");
1822 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1823 final Folder parent = file.getFolder();
1825 throw new ObjectNotFoundException("The specified file has no parent folder");
1826 if (!file.hasDeletePermission(user))
1827 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
1829 parent.removeFile(file);
1830 for (final FileBody body : file.getBodies())
1831 filesToRemove.add(body.getStoredFilePath());
1834 //then remove physical files if everything is ok
1835 for(String physicalFileName : filesToRemove)
1836 deleteActualFile(physicalFileName);
1837 //then unindex deleted files
1838 for(Long fileId : fileIds)
1839 indexFile(fileId, true);
1844 * @see gr.ebs.gss.server.ejb.ExternalAPI#moveFilesToTrash(java.lang.Long, java.util.List)
1847 public void moveFilesToTrash(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1848 for(Long l : fileIds)
1849 moveFileToTrash(userId, l);
1854 public void removeFilesFromTrash(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1855 for(Long l : fileIds)
1856 removeFileFromTrash(userId, l);
1861 public Nonce createNonce(Long userId) throws ObjectNotFoundException {
1863 throw new ObjectNotFoundException("No user specified");
1864 User user = dao.getEntityById(User.class, userId);
1865 Nonce nonce = Nonce.createNonce(user.getId());
1871 public Nonce getNonce(String nonce, Long userId) throws ObjectNotFoundException {
1873 throw new ObjectNotFoundException("No user specified");
1875 throw new ObjectNotFoundException("No nonce specified");
1876 return dao.getNonce(nonce, userId);
1880 public void removeNonce(Long id) throws ObjectNotFoundException {
1882 throw new ObjectNotFoundException("No nonce specified");
1883 Nonce nonce = dao.getEntityById(Nonce.class, id);
1888 public void activateUserNonce(Long userId, String nonce, Date nonceExpiryDate) throws ObjectNotFoundException {
1890 throw new ObjectNotFoundException("No user specified");
1891 User user = dao.getEntityById(User.class, userId);
1892 user.setNonce(nonce);
1893 user.setNonceExpiryDate(nonceExpiryDate);
1897 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUserStatistics(java.lang.Long)
1900 public StatsDTO getUserStatistics(Long userId) throws ObjectNotFoundException {
1902 throw new ObjectNotFoundException("No user specified");
1903 StatsDTO stats = new StatsDTO();
1904 stats.setFileCount(dao.getFileCount(userId));
1905 Long fileSize = dao.getFileSize(userId);
1906 stats.setFileSize(fileSize);
1907 Long quota = getQuota(userId);
1908 Long quotaLeft = quota - fileSize;
1909 stats.setQuotaLeftSize(quotaLeft);
1914 * @see gr.ebs.gss.server.ejb.ExternalAPI#getVersions(java.lang.Long, java.lang.Long)
1917 public List<FileBodyDTO> getVersions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1919 throw new ObjectNotFoundException("No user specified");
1921 throw new ObjectNotFoundException("No file specified");
1922 User user = dao.getEntityById(User.class, userId);
1923 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
1924 if(!header.hasReadPermission(user))
1925 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1926 List<FileBodyDTO> result = new LinkedList<FileBodyDTO>();
1927 for(int i = header.getBodies().size()-1 ; i>=0; i--)
1928 result.add(header.getBodies().get(i).getDTO());
1933 * @see gr.ebs.gss.server.ejb.ExternalAPI#removeVersion(java.lang.Long, java.lang.Long, java.lang.Long)
1936 public void removeVersion(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
1938 throw new ObjectNotFoundException("No user specified");
1940 throw new ObjectNotFoundException("No file specified");
1942 throw new ObjectNotFoundException("No body specified");
1943 User user = dao.getEntityById(User.class, userId);
1944 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
1945 if(!header.hasWritePermission(user))
1946 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1947 FileBody body = dao.getEntityById(FileBody.class, bodyId);
1948 if(body.equals(header.getCurrentBody())){
1950 if(header.getBodies().size() == 1)
1951 throw new InsufficientPermissionsException("You cant delete this version, Delete file instead!");
1952 for(FileBody b : header.getBodies())
1953 if(b.getVersion() == body.getVersion()-1)
1954 header.setCurrentBody(b);
1956 deleteActualFile(body.getStoredFilePath());
1957 header.getBodies().remove(body);
1963 public void restoreVersion(Long userId, Long fileId, int version) throws ObjectNotFoundException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1965 throw new ObjectNotFoundException("No user specified");
1967 throw new ObjectNotFoundException("No file specified");
1968 User user = dao.getEntityById(User.class, userId);
1969 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
1970 if(!header.hasWritePermission(user))
1971 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1972 FileBody body = dao.getFileVersion(fileId, version);
1973 final File fileContents = new File(body.getStoredFilePath());
1976 updateFileContents(userId, fileId, body.getMimeType(), new FileInputStream(fileContents) );
1977 } catch (FileNotFoundException e) {
1978 throw new GSSIOException(e);
1984 * @see gr.ebs.gss.server.ejb.ExternalAPI#removeOldVersions(java.lang.Long, java.lang.Long)
1987 public void removeOldVersions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1989 throw new ObjectNotFoundException("No user specified");
1991 throw new ObjectNotFoundException("No file specified");
1992 User user = dao.getEntityById(User.class, userId);
1993 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
1994 if(!header.hasWritePermission(user))
1995 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1996 Iterator<FileBody> it = header.getBodies().iterator();
1997 while(it.hasNext()){
1998 FileBody body = it.next();
1999 if(!body.equals(header.getCurrentBody())){
2000 deleteActualFile(body.getStoredFilePath());
2005 header.getCurrentBody().setVersion(1);
2010 * @see gr.ebs.gss.server.ejb.ExternalAPI#toggleFileVersioning(java.lang.Long, java.lang.Long, boolean)
2013 public void toggleFileVersioning(Long userId, Long fileId, boolean versioned) throws ObjectNotFoundException, InsufficientPermissionsException {
2015 throw new ObjectNotFoundException("No user specified");
2017 throw new ObjectNotFoundException("No file specified");
2018 User user = dao.getEntityById(User.class, userId);
2019 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
2020 if(!header.hasWritePermission(user))
2021 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2022 if(!header.isVersioned() == versioned){
2023 if(header.isVersioned())
2024 removeOldVersions(userId, fileId);
2025 header.setVersioned(versioned);
2031 * Gets the quota left for specified userId
2035 private Long getQuotaLeft(Long userId){
2036 Long fileSize = dao.getFileSize(userId);
2037 Long quota = getQuota(userId);
2038 return quota - fileSize;
2042 * Gets the quota for specified userId
2046 private Long getQuota(@SuppressWarnings("unused") Long userId){
2047 Long quota = getConfiguration().getLong("quota", new Long(52428800L));
2051 public void rebuildSolrIndex() {
2052 MessageProducer sender = null;
2053 Session session = null;
2054 Connection qConn = null;
2056 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
2057 DocumentBuilder db = dbf.newDocumentBuilder();
2058 Document doc = db.newDocument();
2059 Node root = doc.createElement("delete");
2060 doc.appendChild(root);
2061 Node queryNode = doc.createElement("query");
2062 root.appendChild(queryNode);
2063 queryNode.appendChild(doc.createTextNode("*:*"));
2065 TransformerFactory fact = TransformerFactory.newInstance();
2066 Transformer trans = fact.newTransformer();
2067 trans.setOutputProperty(OutputKeys.INDENT, "yes");
2068 StringWriter sw = new StringWriter();
2069 StreamResult sr = new StreamResult(sw);
2070 DOMSource source = new DOMSource(doc);
2071 trans.transform(source, sr);
2072 logger.debug(sw.toString());
2074 HttpClient httpClient = new HttpClient();
2075 PostMethod method = new PostMethod(getConfiguration().getString("solrUpdateUrl"));
2076 method.setRequestEntity(new StringRequestEntity(sw.toString()));
2079 String response = null;
2081 statusCode = httpClient.executeMethod(method);
2082 logger.debug("HTTP status: " + statusCode);
2083 response = method.getResponseBodyAsString();
2084 logger.debug(response);
2086 if (statusCode != 200 && retryCount < 3)
2088 Thread.sleep(10000); //Give Solr a little time to be available
2089 } catch (InterruptedException e) {
2091 } while (statusCode != 200 && retryCount < 3);
2092 method.releaseConnection();
2093 if (statusCode != 200)
2094 throw new EJBException("Cannot clear Solr index. Solr response is:\n" + response);
2095 List<Long> fileIds = dao.getAllFileIds();
2097 Context jndiCtx = new InitialContext();
2098 ConnectionFactory factory = (QueueConnectionFactory) jndiCtx.lookup("java:/JmsXA");
2099 Queue queue = (Queue) jndiCtx.lookup("queue/gss-indexingQueue");
2100 qConn = factory.createConnection();
2101 session = qConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
2102 sender = session.createProducer(queue);
2104 for (Long id : fileIds) {
2105 MapMessage map = session.createMapMessage();
2106 map.setObject("id", id);
2107 map.setBoolean("delete", false);
2110 sendOptimize(httpClient, 0);
2111 } catch (DOMException e) {
2112 throw new EJBException(e);
2113 } catch (TransformerConfigurationException e) {
2114 throw new EJBException(e);
2115 } catch (IllegalArgumentException e) {
2116 throw new EJBException(e);
2117 } catch (HttpException e) {
2118 throw new EJBException(e);
2119 } catch (UnsupportedEncodingException e) {
2120 throw new EJBException(e);
2121 } catch (ParserConfigurationException e) {
2122 throw new EJBException(e);
2123 } catch (TransformerException e) {
2124 throw new EJBException(e);
2125 } catch (IOException e) {
2126 throw new EJBException(e);
2127 } catch (NamingException e) {
2128 throw new EJBException(e);
2129 } catch (JMSException e) {
2130 throw new EJBException(e);
2136 if (session != null)
2141 catch (JMSException e) {
2148 * Sends a optimize message to the solr server
2151 * @param retryCount If the commit fails, it is retried three times. This parameter is passed in the recursive
2152 * calls to stop the recursion
2153 * @throws UnsupportedEncodingException
2154 * @throws IOException
2155 * @throws HttpException
2157 private void sendOptimize(HttpClient httpClient, int retryCount) throws UnsupportedEncodingException, IOException, HttpException {
2158 PostMethod method = null;
2160 logger.debug("Optimize retry: " + retryCount);
2161 method = new PostMethod(getConfiguration().getString("solrUpdateUrl"));
2162 method.setRequestEntity(new StringRequestEntity("<optimize/>", "text/xml", "iso8859-1"));
2163 int statusCode = httpClient.executeMethod(method);
2164 logger.debug("HTTP status: " + statusCode);
2165 String response = method.getResponseBodyAsString();
2166 logger.debug(response);
2167 if (statusCode != 200 && retryCount < 2) {
2169 Thread.sleep(10000); //Give Solr a little time to be available
2170 } catch (InterruptedException e) {
2172 sendOptimize(httpClient, retryCount + 1);
2177 method.releaseConnection();
2181 public FileHeaderDTO createFile(Long userId, Long folderId, String name, String mimeType, long fileSize, String filePath)
2182 throws DuplicateNameException, ObjectNotFoundException, GSSIOException,
2183 InsufficientPermissionsException, QuotaExceededException {
2186 throw new ObjectNotFoundException("No user specified");
2187 if (folderId == null)
2188 throw new ObjectNotFoundException("No folder specified");
2189 String contentType = mimeType;
2190 if (StringUtils.isEmpty(mimeType))
2191 contentType = DEFAULT_MIME_TYPE;
2192 if (StringUtils.isEmpty(name))
2193 throw new ObjectNotFoundException("No file name specified");
2194 if (dao.existsFolderOrFile(folderId, name))
2195 throw new DuplicateNameException("A folder or file with the name '" + name +
2196 "' already exists at this level");
2198 // Do the actual work.
2199 Folder parent = null;
2201 parent = dao.getEntityById(Folder.class, folderId);
2202 } catch (final ObjectNotFoundException onfe) {
2203 // Supply a more accurate problem description.
2204 throw new ObjectNotFoundException("Parent folder not found");
2206 final User owner = dao.getEntityById(User.class, userId);
2207 if (!parent.hasWritePermission(owner))
2208 throw new InsufficientPermissionsException("You don't have the permissions to write to this folder");
2209 final FileHeader file = new FileHeader();
2211 parent.addFile(file);
2212 // set file owner to folder owner
2213 file.setOwner(parent.getOwner());
2215 final Date now = new Date();
2216 final AuditInfo auditInfo = new AuditInfo();
2217 auditInfo.setCreatedBy(owner);
2218 auditInfo.setCreationDate(now);
2219 auditInfo.setModifiedBy(owner);
2220 auditInfo.setModificationDate(now);
2221 file.setAuditInfo(auditInfo);
2222 // TODO set the proper versioning flag on creation
2223 file.setVersioned(false);
2225 for (final Permission p : parent.getPermissions()) {
2226 final Permission permission = new Permission();
2227 permission.setGroup(p.getGroup());
2228 permission.setUser(p.getUser());
2229 permission.setRead(p.getRead());
2230 permission.setWrite(p.getWrite());
2231 permission.setModifyACL(p.getModifyACL());
2232 file.addPermission(permission);
2235 // Create the file body.
2237 createFileBody(name, contentType, fileSize, filePath, file, auditInfo);
2238 } catch (FileNotFoundException e) {
2239 throw new GSSIOException(e);
2242 indexFile(file.getId(), false);
2244 return file.getDTO();
2248 * @see gr.ebs.gss.server.ejb.ExternalAPI#updateFileContents(java.lang.Long, java.lang.Long, java.lang.String, java.io.InputStream)
2250 public FileHeaderDTO updateFileContents(Long userId, Long fileId, String mimeType, long fileSize, String filePath) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
2252 throw new ObjectNotFoundException("No user specified");
2254 throw new ObjectNotFoundException("No file specified");
2255 String contentType = mimeType;
2257 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
2259 // if no mime type or the generic mime type is defined by the client, then try to identify it from the filename extension
2260 if (StringUtils.isEmpty(mimeType) || "application/octet-stream".equals(mimeType)
2261 || "application/download".equals(mimeType) || "application/force-download".equals(mimeType)
2262 || "octet/stream".equals(mimeType) || "application/unknown".equals(mimeType))
2263 contentType = identifyMimeType(file.getName());
2265 final User owner = dao.getEntityById(User.class, userId);
2266 if (!file.hasWritePermission(owner))
2267 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2268 final Date now = new Date();
2269 final AuditInfo auditInfo = new AuditInfo();
2270 auditInfo.setCreatedBy(owner);
2271 auditInfo.setCreationDate(now);
2272 auditInfo.setModifiedBy(owner);
2273 auditInfo.setModificationDate(now);
2275 createFileBody(file.getName(), contentType, fileSize, filePath, file, auditInfo);
2276 } catch (FileNotFoundException e) {
2277 throw new GSSIOException(e);
2280 indexFile(fileId, false);
2281 return file.getDTO();
2285 * Helper method for identifying mime type by examining the filename extension
2288 * @return the mime type
2290 private String identifyMimeType(String filename) {
2291 if (filename.indexOf('.') != -1) {
2292 String extension = filename.substring(filename.lastIndexOf('.')).toLowerCase(Locale.ENGLISH);
2293 if (".doc".equals(extension))
2294 return "application/msword";
2295 else if (".xls".equals(extension))
2296 return "application/vnd.ms-excel";
2297 else if (".ppt".equals(extension))
2298 return "application/vnd.ms-powerpoint";
2299 else if (".pdf".equals(extension))
2300 return "application/pdf";
2301 else if (".gif".equals(extension))
2303 else if (".jpg".equals(extension) || ".jpeg".equals(extension) || ".jpe".equals(extension))
2304 return "image/jpeg";
2305 else if (".tiff".equals(extension) || ".tif".equals(extension))
2306 return "image/tiff";
2307 else if (".png".equals(extension))
2309 else if (".bmp".equals(extension))
2312 // when all else fails assign the default mime type
2313 return DEFAULT_MIME_TYPE;
2317 * Helper method to create a new file body and attach it as the current body
2318 * of the provided file header.
2320 * @param name the original file name
2321 * @param mimeType the content type
2322 * @param fileSize the uploaded file size
2323 * @param filePath the uploaded file full path
2324 * @param header the file header that will be associated with the new body
2325 * @param auditInfo the audit info
2326 * @param owner the owner of the file
2327 * @throws FileNotFoundException
2328 * @throws QuotaExceededException
2330 private void createFileBody(String name, String mimeType, long fileSize, String filePath,
2331 FileHeader header, AuditInfo auditInfo)
2332 throws FileNotFoundException, QuotaExceededException {
2334 long currentTotalSize = 0;
2335 if (!header.isVersioned() && header.getCurrentBody() != null && header.getBodies() != null)
2336 currentTotalSize = header.getTotalSize();
2337 Long quotaLeft = getQuotaLeft(header.getOwner().getId());
2338 if(quotaLeft < fileSize-currentTotalSize) {
2339 // quota exceeded -> delete the file
2340 deleteActualFile(filePath);
2341 throw new QuotaExceededException("Not enough free space available");
2344 FileBody body = new FileBody();
2346 // if no mime type or the generic mime type is defined by the client, then try to identify it from the filename extension
2347 if (StringUtils.isEmpty(mimeType) || "application/octet-stream".equals(mimeType)
2348 || "application/download".equals(mimeType) || "application/force-download".equals(mimeType)
2349 || "octet/stream".equals(mimeType) || "application/unknown".equals(mimeType))
2350 body.setMimeType(identifyMimeType(name));
2352 body.setMimeType(mimeType);
2353 body.setAuditInfo(auditInfo);
2354 body.setFileSize(fileSize);
2355 body.setOriginalFilename(name);
2356 body.setStoredFilePath(filePath);
2357 //CLEAR OLD VERSION IF FILE IS NOT VERSIONED AND GETS UPDATED
2358 if(!header.isVersioned() && header.getCurrentBody() != null){
2359 header.setCurrentBody(null);
2360 if (header.getBodies() != null) {
2361 Iterator<FileBody> it = header.getBodies().iterator();
2362 while(it.hasNext()){
2363 FileBody bo = it.next();
2364 deleteActualFile(bo.getStoredFilePath());
2372 header.addBody(body);
2378 @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
2379 public File uploadFile(InputStream stream, Long userId) throws IOException, ObjectNotFoundException {
2381 throw new ObjectNotFoundException("No user specified");
2382 User owner = dao.getEntityById(User.class, userId);
2384 throw new ObjectNotFoundException("No user specified");
2385 long start = 0, end = 0;
2386 if (logger.isDebugEnabled())
2387 start = System.currentTimeMillis();
2388 File result = new File(generateRepositoryFilePath());
2390 final FileOutputStream output = new FileOutputStream(result);
2391 final byte[] buffer = new byte[UPLOAD_BUFFER_SIZE];
2394 while (-1 != (n = stream.read(buffer)))
2395 output.write(buffer, 0, n);
2398 } catch (IOException e) {
2399 if (!result.delete())
2400 logger.warn("Could not delete " + result.getPath());
2403 if (logger.isDebugEnabled()) {
2404 end = System.currentTimeMillis();
2405 logger.debug("Time to upload: " + (end - start) + " (msec)");
2411 public void createFileUploadProgress(Long userId, String filename, Long bytesTransfered, Long fileSize) throws ObjectNotFoundException{
2414 throw new ObjectNotFoundException("No user specified");
2415 User user = dao.getEntityById(User.class, userId);
2416 FileUploadStatus status = dao.getFileUploadStatus(userId, filename);
2418 status = new FileUploadStatus();
2419 status.setOwner(user);
2420 status.setFilename(filename);
2421 status.setBytesUploaded(bytesTransfered);
2422 status.setFileSize(fileSize);
2426 status.setBytesUploaded(bytesTransfered);
2427 status.setFileSize(fileSize);
2433 public void removeFileUploadProgress(Long userId, String filename) throws ObjectNotFoundException{
2435 throw new ObjectNotFoundException("No user specified");
2436 FileUploadStatus status = dao.getFileUploadStatus(userId, filename);
2442 public FileUploadStatus getFileUploadStatus(Long userId, String fileName) {
2443 return dao.getFileUploadStatus(userId, fileName);
2447 public FolderDTO getFolderWithSubfolders(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
2449 throw new ObjectNotFoundException("No user specified");
2450 if (folderId == null)
2451 throw new ObjectNotFoundException("No folder specified");
2452 final User user = dao.getEntityById(User.class, userId);
2453 final Folder folder = dao.getEntityById(Folder.class, folderId);
2454 // Check permissions
2455 if (!folder.hasReadPermission(user))
2456 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
2457 List<FolderDTO> subfolders = new ArrayList<FolderDTO>();
2458 if (folder.hasReadPermission(user))
2459 for (Folder f : folder.getSubfolders())
2460 if (f.hasReadPermission(user) && !f.isDeleted())
2461 subfolders.add(f.getDTO());
2462 FolderDTO result = folder.getDTO();
2463 result.setSubfolders(subfolders);
2464 return folder.getDTO();
2468 public FolderDTO getFolderWithSubfolders(Long userId, Long callingUserId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
2470 throw new ObjectNotFoundException("No user specified");
2471 if (folderId == null)
2472 throw new ObjectNotFoundException("No folder specified");
2473 User user = dao.getEntityById(User.class, callingUserId);
2474 Folder folder = dao.getEntityById(Folder.class, folderId);
2475 // Check permissions
2476 if (!folder.hasReadPermission(user))
2477 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
2479 FolderDTO result = folder.getDTO();
2480 result.setSubfolders(getSharedSubfolders(userId, callingUserId, folder.getId()));
2485 public FileBodyDTO getFileVersion(Long userId, Long fileId, int version)
2486 throws ObjectNotFoundException, InsufficientPermissionsException {
2488 throw new ObjectNotFoundException("No user specified");
2490 throw new ObjectNotFoundException("No file specified");
2492 throw new ObjectNotFoundException("No valid version specified");
2493 User user = dao.getEntityById(User.class, userId);
2494 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
2495 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
2496 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2497 FileBody body = dao.getFileVersion(fileId, version);
2498 return body.getDTO();
2502 public User updateUserPolicyAcceptance(Long userId, boolean isAccepted) throws ObjectNotFoundException {
2504 throw new ObjectNotFoundException("No user specified");
2505 User user = dao.getEntityById(User.class, userId);
2506 user.setAcceptedPolicy(isAccepted);
2511 public void updateAccounting(User user, Date date, long bandwidthDiff) {
2512 dao.updateAccounting(user, date, bandwidthDiff);
2516 public boolean canReadFolder(Long userId, Long folderId) throws ObjectNotFoundException {
2518 throw new ObjectNotFoundException("No user specified");
2519 if (folderId == null)
2520 throw new ObjectNotFoundException("No folder specified");
2521 User user = dao.getEntityById(User.class, userId);
2522 Folder folder = dao.getEntityById(Folder.class, folderId);
2523 // Check permissions
2524 if (!folder.hasReadPermission(user))
2530 * Reset WebDAV password for given user.
2533 * @return the new password
2534 * @throws ObjectNotFoundException
2537 public String resetWebDAVPassword(Long userId) throws ObjectNotFoundException {
2539 throw new ObjectNotFoundException("No user specified");
2540 User user = dao.getEntityById(User.class, userId);
2541 user.generateWebDAVPassword();
2542 return user.getWebDAVPassword();