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 gr.ebs.gss.client.exceptions.DuplicateNameException;
22 import gr.ebs.gss.client.exceptions.GSSIOException;
23 import gr.ebs.gss.client.exceptions.InsufficientPermissionsException;
24 import gr.ebs.gss.client.exceptions.ObjectNotFoundException;
25 import gr.ebs.gss.client.exceptions.QuotaExceededException;
26 import gr.ebs.gss.server.configuration.GSSConfigurationFactory;
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.Random;
61 import java.util.StringTokenizer;
64 import javax.ejb.EJBException;
65 import javax.ejb.Stateless;
66 import javax.ejb.TransactionAttribute;
67 import javax.ejb.TransactionAttributeType;
68 import javax.jms.Connection;
69 import javax.jms.ConnectionFactory;
70 import javax.jms.JMSException;
71 import javax.jms.MapMessage;
72 import javax.jms.MessageProducer;
73 import javax.jms.Queue;
74 import javax.jms.QueueConnectionFactory;
75 import javax.jms.Session;
76 import javax.jws.WebMethod;
77 import javax.naming.Context;
78 import javax.naming.InitialContext;
79 import javax.naming.NamingException;
80 import javax.xml.parsers.DocumentBuilder;
81 import javax.xml.parsers.DocumentBuilderFactory;
82 import javax.xml.parsers.ParserConfigurationException;
83 import javax.xml.transform.OutputKeys;
84 import javax.xml.transform.Transformer;
85 import javax.xml.transform.TransformerConfigurationException;
86 import javax.xml.transform.TransformerException;
87 import javax.xml.transform.TransformerFactory;
88 import javax.xml.transform.dom.DOMSource;
89 import javax.xml.transform.stream.StreamResult;
91 import org.apache.commons.configuration.BaseConfiguration;
92 import org.apache.commons.configuration.ConfigurationException;
93 import org.apache.commons.configuration.DataConfiguration;
94 import org.apache.commons.httpclient.HttpClient;
95 import org.apache.commons.httpclient.HttpException;
96 import org.apache.commons.httpclient.NameValuePair;
97 import org.apache.commons.httpclient.methods.GetMethod;
98 import org.apache.commons.httpclient.methods.PostMethod;
99 import org.apache.commons.httpclient.methods.StringRequestEntity;
100 import org.apache.commons.lang.StringUtils;
101 import org.apache.commons.logging.Log;
102 import org.apache.commons.logging.LogFactory;
103 import org.w3c.dom.DOMException;
104 import org.w3c.dom.Document;
105 import org.w3c.dom.Node;
106 import org.w3c.dom.NodeList;
107 import org.xml.sax.SAXException;
110 * The concrete implementation of the ExternalAPI interface.
115 public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
120 private static DataConfiguration conf = null;
124 * The default MIME type for files without an explicit one.
126 private static final String DEFAULT_MIME_TYPE = "application/octet-stream";
129 * The size of the buffer that is used to temporarily store chunks of
130 * uploaded files, while storing them to the file repository.
132 private static final int UPLOAD_BUFFER_SIZE = 1024 * 4;
137 private static Log logger = LogFactory.getLog(ExternalAPIBean.class);
141 conf = GSSConfigurationFactory.getConfiguration();
143 catch (ConfigurationException e) {
144 // Use empty configuration, so we get no NPE but default values
145 conf = new DataConfiguration(new BaseConfiguration());
146 logger.error("Error in ExternalAPI initialization!!! GSS IS RUNNING WITH DEFAULT VALUES",e);
150 * Injected reference to the GSSDAO data access facade.
157 * A cached random number generator for creating unique filenames.
159 private static Random random = new Random();
162 public FolderDTO getRootFolder(Long userId) throws ObjectNotFoundException {
164 throw new ObjectNotFoundException("No user specified");
165 Folder folder = dao.getRootFolder(userId);
166 return folder.getDTO();
172 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFolder(java.lang.Long)
174 public FolderDTO getFolder(final Long userId, final Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
176 throw new ObjectNotFoundException("No user specified");
177 if (folderId == null)
178 throw new ObjectNotFoundException("No folder specified");
179 final User user = dao.getEntityById(User.class, userId);
180 final Folder folder = dao.getEntityById(Folder.class, folderId);
182 if (!folder.hasReadPermission(user))
183 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
184 return folder.getDTO();
188 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUser(java.lang.Long)
190 public User getUser(Long userId) throws ObjectNotFoundException {
192 throw new ObjectNotFoundException("No user specified");
193 return dao.getEntityById(User.class, userId);
197 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUserDTO(java.lang.Long)
199 public UserDTO getUserDTO(final Long userId) throws ObjectNotFoundException {
200 return getUser(userId).getDTO();
206 * @see gr.ebs.gss.server.ejb.ExternalAPI#getGroup(java.lang.Long)
208 public GroupDTO getGroup(final Long groupId) throws ObjectNotFoundException {
210 throw new ObjectNotFoundException("No group specified");
211 final Group group = dao.getEntityById(Group.class, groupId);
212 return group.getDTO();
216 public GroupDTO getGroup(Long userId, String name) throws ObjectNotFoundException {
218 throw new ObjectNotFoundException("No user specified");
220 throw new ObjectNotFoundException("No group specified");
221 User user = dao.getEntityById(User.class, userId);
222 List<Group> groups = user.getGroupsSpecified();
223 for (Group group: groups)
224 if (group.getName().equals(name))
225 return group.getDTO();
226 throw new ObjectNotFoundException("Group " + name + " not found");
232 * @see gr.ebs.gss.server.ejb.ExternalAPI#getGroups(java.lang.Long)
234 public List<GroupDTO> getGroups(final Long userId) throws ObjectNotFoundException {
236 throw new ObjectNotFoundException("No user specified");
237 final List<Group> groups = dao.getGroups(userId);
238 final List<GroupDTO> result = new ArrayList<GroupDTO>();
239 for (final Group g : groups)
240 result.add(g.getDTO());
245 public List<FileHeaderDTO> getFiles(Long userId, Long folderId, boolean ignoreDeleted)
246 throws ObjectNotFoundException, InsufficientPermissionsException {
249 throw new ObjectNotFoundException("No user specified");
250 if (folderId == null)
251 throw new ObjectNotFoundException("No folder specified");
252 User user = dao.getEntityById(User.class, userId);
253 Folder folder = dao.getEntityById(Folder.class, folderId);
254 if (!folder.hasReadPermission(user))
255 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
256 // Do the actual work.
257 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
258 List<FileHeader> files = dao.getFiles(folderId, ignoreDeleted);
259 for (FileHeader f : files)
260 result.add(f.getDTO());
267 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsers(java.lang.Long,
270 public List<UserDTO> getUsers(final Long userId, final Long groupId) throws ObjectNotFoundException {
273 throw new ObjectNotFoundException("No user specified");
275 throw new ObjectNotFoundException("No group specified");
277 // Do the actual work.
278 final List<User> users = dao.getUsers(groupId);
279 final List<UserDTO> result = new ArrayList<UserDTO>();
280 for (final User u : users)
281 result.add(u.getDTO());
286 public void createFolder(Long userId, Long parentId, String name)
287 throws DuplicateNameException, ObjectNotFoundException, InsufficientPermissionsException {
290 throw new ObjectNotFoundException("No user specified");
291 if (StringUtils.isEmpty(name))
292 throw new ObjectNotFoundException("New folder name is empty");
293 if (parentId == null)
294 throw new ObjectNotFoundException("No parent specified");
295 if (dao.existsFolderOrFile(parentId, name))
296 throw new DuplicateNameException("A folder or file with the name '" +
297 name + "' already exists at this level");
299 User creator = dao.getEntityById(User.class, userId);
301 Folder parent = null;
303 parent = dao.getEntityById(Folder.class, parentId);
304 } catch (ObjectNotFoundException onfe) {
305 // Supply a more accurate problem description.
306 throw new ObjectNotFoundException("Parent folder not found");
308 if (!parent.hasWritePermission(creator))
309 throw new InsufficientPermissionsException("You don't have the permissions" +
310 " to write to this folder");
312 // Do the actual work.
313 createFolder(name, parent, creator);
317 * Create a new folder with the provided name, parent and owner.
324 private void createFolder(String name, Folder parent, User creator) {
325 Folder folder = new Folder();
326 folder.setName(name);
327 if (parent != null) {
328 parent.addSubfolder(folder);
329 folder.setOwner(parent.getOwner());
331 folder.setOwner(creator);
333 Date now = new Date();
334 AuditInfo auditInfo = new AuditInfo();
335 auditInfo.setCreatedBy(creator);
336 auditInfo.setCreationDate(now);
337 auditInfo.setModifiedBy(creator);
338 auditInfo.setModificationDate(now);
339 folder.setAuditInfo(auditInfo);
342 for (Permission p : parent.getPermissions()) {
343 Permission permission = new Permission();
344 permission.setGroup(p.getGroup());
345 permission.setUser(p.getUser());
346 permission.setRead(p.getRead());
347 permission.setWrite(p.getWrite());
348 permission.setModifyACL(p.getModifyACL());
349 folder.addPermission(permission);
352 Permission permission = new Permission();
353 permission.setUser(creator);
354 permission.setRead(true);
355 permission.setWrite(true);
356 permission.setModifyACL(true);
357 folder.addPermission(permission);
365 * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteFolder(java.lang.Long,
368 public void deleteFolder(final Long userId, final Long folderId) throws InsufficientPermissionsException, ObjectNotFoundException {
371 throw new ObjectNotFoundException("No user specified");
372 if (folderId == null)
373 throw new ObjectNotFoundException("No folder specified");
375 // Do the actual work.
376 final Folder folder = dao.getEntityById(Folder.class, folderId);
377 final Folder parent = folder.getParent();
379 throw new ObjectNotFoundException("Deleting the root folder is not allowed");
380 final User user = dao.getEntityById(User.class, userId);
381 if (!folder.hasDeletePermission(user)) {
382 logger.info("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
383 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
385 parent.removeSubfolder(folder);
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 void 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 createFile(userId, folderId, name, mimeType, file);
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 = conf.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 final File fileContents = new File(body.getStoredFilePath());
596 if (!fileContents.delete())
597 logger.error("Could not delete file " + body.getStoredFilePath());
600 indexFile(fileId, true);
606 * @see gr.ebs.gss.server.ejb.ExternalAPI#createTag(java.lang.Long,
607 * java.lang.Long, java.lang.String)
609 public void createTag(final Long userId, final Long fileHeaderId, final String tag) throws ObjectNotFoundException {
611 throw new ObjectNotFoundException("No user specified");
612 if (fileHeaderId == null)
613 throw new ObjectNotFoundException("No file specified");
614 if (StringUtils.isEmpty(tag))
615 throw new ObjectNotFoundException("Tag is empty");
617 final User user = dao.getEntityById(User.class, userId);
618 final FileHeader fh = dao.getEntityById(FileHeader.class, fileHeaderId);
619 user.addTag(fh, tag);
623 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUserTags(java.lang.Long)
625 @WebMethod(operationName = "getUserTags")
626 public Set<String> getUserTags(final Long userId) throws ObjectNotFoundException {
627 return dao.getUserTags(userId);
631 * @see gr.ebs.gss.server.ejb.ExternalAPI#updateFile(java.lang.Long, java.lang.Long, java.lang.String, java.util.Set)
633 public void updateFile(Long userId, Long fileId, String name, String tagSet) throws ObjectNotFoundException, InsufficientPermissionsException {
635 throw new ObjectNotFoundException("No user specified");
637 throw new ObjectNotFoundException("No file specified");
638 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
639 User user = dao.getEntityById(User.class, userId);
640 if (!file.hasWritePermission(user))
641 throw new InsufficientPermissionsException("User " + user.getId() + " cannot update file " + file.getName() + "(" + file.getId() + ")");
645 List<FileTag> tags = file.getFileTags();
647 if (tagSet != null) {
648 Iterator<FileTag> i = tags.iterator();
649 while (i.hasNext()) {
650 FileTag tag = i.next();
657 StringTokenizer st = new StringTokenizer(tagSet, ",");
658 while (st.hasMoreTokens())
659 new FileTag(user, file, st.nextToken().trim());
662 // Re-index the file if it was modified.
663 if (name != null || tagSet != null)
664 indexFile(fileId, false);
668 public InputStream getFileContents(Long userId, Long fileId)
669 throws ObjectNotFoundException, InsufficientPermissionsException {
671 throw new ObjectNotFoundException("No user specified");
673 throw new ObjectNotFoundException("No file specified");
675 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
676 User user = dao.getEntityById(User.class, userId);
677 if (!header.hasReadPermission(user)) {
678 logger.info("User " + user.getId() + " cannot read file " + header.getName() + "(" + fileId + ")");
679 throw new InsufficientPermissionsException("You don't have the necessary permissions");
682 File f = new File(header.getCurrentBody().getStoredFilePath());
684 return new FileInputStream(f);
685 } catch (FileNotFoundException e) {
686 logger.error("Could not locate the contents of file " + f.getAbsolutePath());
687 throw new ObjectNotFoundException("The file contents could not be located");
692 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFileContents(java.lang.Long, java.lang.Long, java.lang.Long)
694 public InputStream getFileContents(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
696 throw new ObjectNotFoundException("No user specified");
698 throw new ObjectNotFoundException("No file specified");
700 throw new ObjectNotFoundException("No file specified");
702 final FileHeader header = dao.getEntityById(FileHeader.class, fileId);
703 final FileBody body = dao.getEntityById(FileBody.class, bodyId);
704 final User user = dao.getEntityById(User.class, userId);
705 if (!header.hasReadPermission(user)) {
706 logger.info("User " + user.getId() + " cannot read file " + header.getName() + "(" + fileId + ")");
707 throw new InsufficientPermissionsException("You don't have the necessary permissions");
710 File f = new File(body.getStoredFilePath());
712 return new FileInputStream(f);
713 } catch (FileNotFoundException e) {
714 logger.error("Could not locate the contents of file " + f.getAbsolutePath());
715 throw new ObjectNotFoundException("The file contents could not be located");
720 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFile(java.lang.Long, java.lang.Long)
722 public FileHeaderDTO getFile(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
724 throw new ObjectNotFoundException("No user specified");
726 throw new ObjectNotFoundException("No file specified");
727 final User user = dao.getEntityById(User.class, userId);
728 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
729 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
730 throw new InsufficientPermissionsException("You don't have the necessary permissions");
731 return file.getDTO();
735 public FileBodyDTO getFileBody(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
737 throw new ObjectNotFoundException("No user specified");
739 throw new ObjectNotFoundException("No file specified");
740 User user = dao.getEntityById(User.class, userId);
741 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
742 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
743 throw new InsufficientPermissionsException("You don't have the necessary permissions");
744 FileBody body = dao.getEntityById(FileBody.class, bodyId);
745 return body.getDTO();
749 public Object getResourceAtPath(Long ownerId, String path, boolean ignoreDeleted)
750 throws ObjectNotFoundException {
752 throw new ObjectNotFoundException("No user specified");
753 if (StringUtils.isEmpty(path))
754 throw new ObjectNotFoundException("No path specified");
756 User owner = dao.getEntityById(User.class, ownerId);
757 List<String> pathElements = new ArrayList<String>();
758 StringTokenizer st = new StringTokenizer(path, "/");
759 while (st.hasMoreTokens())
760 pathElements.add(st.nextToken());
761 if (pathElements.size() < 1)
762 return getRootFolder(owner.getId());
763 // Store the last element, since it requires special handling.
764 String lastElement = pathElements.remove(pathElements.size() - 1);
765 FolderDTO cursor = getRootFolder(owner.getId());
766 // Traverse and verify the specified folder path.
767 for (String pathElement : pathElements) {
768 cursor = getFolder(cursor.getId(), pathElement);
769 if (cursor.isDeleted())
770 throw new ObjectNotFoundException("Folder " + cursor.getPath() + " not found");
773 // Use the lastElement to retrieve the actual resource.
774 Object resource = null;
776 FileHeaderDTO file = getFile(cursor.getId(), lastElement);
777 if (ignoreDeleted && file.isDeleted())
778 throw new ObjectNotFoundException("Resource not found");
780 } catch (ObjectNotFoundException e) {
781 // Perhaps the requested resource is not a file, so
782 // check for folders as well.
783 FolderDTO folder = getFolder(cursor.getId(), lastElement);
784 if (ignoreDeleted && folder.isDeleted())
785 throw new ObjectNotFoundException("Resource not found");
792 * Retrieve a file for the specified user that has the specified name and
793 * its parent folder has id equal to folderId.
795 * @param userId the ID of the current user
796 * @param folderId the ID of the parent folder
797 * @param name the name of the requested file
798 * @return the file found
799 * @throws ObjectNotFoundException if the specified folder or file was not
800 * found, with the exception message mentioning the precise
803 private FileHeaderDTO getFile(Long folderId, String name) throws ObjectNotFoundException {
804 if (folderId == null)
805 throw new ObjectNotFoundException("No parent folder specified");
806 if (StringUtils.isEmpty(name))
807 throw new ObjectNotFoundException("No file specified");
809 FileHeader file = dao.getFile(folderId, name);
810 return file.getDTO();
814 * Retrieve a folder for the specified user that has the specified name and
815 * its parent folder has id equal to parentId.
817 * @param parentId the ID of the parent folder
818 * @param name the name of the requested folder
819 * @return the folder found
820 * @throws ObjectNotFoundException if the specified folder or parent was not
821 * found, with the exception message mentioning the precise
824 private FolderDTO getFolder(Long parentId, String name) throws ObjectNotFoundException {
825 if (parentId == null)
826 throw new ObjectNotFoundException("No parent folder specified");
827 if (StringUtils.isEmpty(name))
828 throw new ObjectNotFoundException("No folder specified");
830 Folder folder = dao.getFolder(parentId, name);
831 return folder.getDTO();
835 public void updateFileContents(Long userId, Long fileId, String mimeType, InputStream resourceInputStream) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
838 file = uploadFile(resourceInputStream, userId);
839 } catch ( IOException ioe) {
840 // Supply a more accurate problem description.
841 throw new GSSIOException("Problem creating file",ioe);
843 updateFileContents(userId, fileId, mimeType, file);
847 public void copyFile(Long userId, Long fileId, String dest) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
849 throw new ObjectNotFoundException("No user specified");
851 throw new ObjectNotFoundException("No file specified");
852 if (StringUtils.isEmpty(dest))
853 throw new ObjectNotFoundException("No destination specified");
855 Object destination = getResourceAtPath(userId, getParentPath(dest), true);
856 if (!(destination instanceof FolderDTO))
857 throw new ObjectNotFoundException("Destination parent folder not found");
858 FolderDTO parent = (FolderDTO) destination;
859 copyFile(userId, fileId, parent.getId(), getLastElement(dest));
863 public void copyFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
865 throw new ObjectNotFoundException("No user specified");
867 throw new ObjectNotFoundException("No owner specified");
869 throw new ObjectNotFoundException("No file specified");
870 if (StringUtils.isEmpty(dest))
871 throw new ObjectNotFoundException("No destination specified");
873 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
874 if (!(destination instanceof FolderDTO))
875 throw new ObjectNotFoundException("Destination parent folder not found");
876 FolderDTO parent = (FolderDTO) destination;
877 copyFile(userId, fileId, parent.getId(), getLastElement(dest));
881 public void copyFile(Long userId, Long fileId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
883 throw new ObjectNotFoundException("No user specified");
885 throw new ObjectNotFoundException("No file specified");
887 throw new ObjectNotFoundException("No destination specified");
888 if (StringUtils.isEmpty(destName))
889 throw new ObjectNotFoundException("No destination file name specified");
891 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
892 Folder destination = dao.getEntityById(Folder.class, destId);
893 User user = dao.getEntityById(User.class, userId);
894 if (!file.hasReadPermission(user) || !destination.hasWritePermission(user))
895 throw new InsufficientPermissionsException("You don't have the necessary permissions");
896 int versionsNumber = file.getBodies().size();
897 FileBody oldestBody = file.getBodies().get(0);
898 assert oldestBody != null;
899 File contents = new File(oldestBody.getStoredFilePath());
901 createFile(user.getId(), destination.getId(), destName, oldestBody.getMimeType(), new FileInputStream(contents));
902 FileHeader copiedFile = dao.getFile(destination.getId(), destName);
904 if (versionsNumber > 1)
905 for (int i = 1; i < versionsNumber; i++) {
906 FileBody body = file.getBodies().get(i);
908 contents = new File(body.getStoredFilePath());
909 updateFileContents(user.getId(), copiedFile.getId(), body.getMimeType(), new FileInputStream(contents));
911 List<FileTag> tags = file.getFileTags();
912 for (FileTag tag : tags)
913 createTag(userId, copiedFile.getId(), tag.getTag());
915 } catch (FileNotFoundException e) {
916 throw new ObjectNotFoundException("File contents not found for file " + contents.getAbsolutePath());
922 public void copyFolder(Long userId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
924 throw new ObjectNotFoundException("No user specified");
925 if (folderId == null)
926 throw new ObjectNotFoundException("No folder specified");
927 if (StringUtils.isEmpty(dest))
928 throw new ObjectNotFoundException("No destination specified");
930 Object destination = getResourceAtPath(userId, getParentPath(dest), true);
931 if (!(destination instanceof FolderDTO))
932 throw new ObjectNotFoundException("Destination folder not found");
933 FolderDTO parent = (FolderDTO) destination;
934 copyFolder(userId, folderId, parent.getId(), getLastElement(dest));
938 public void copyFolder(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
940 throw new ObjectNotFoundException("No user specified");
941 if (folderId == null)
942 throw new ObjectNotFoundException("No folder specified");
944 throw new ObjectNotFoundException("No destination specified");
945 if (StringUtils.isEmpty(destName))
946 throw new ObjectNotFoundException("No destination folder name specified");
947 Folder folder = dao.getEntityById(Folder.class, folderId);
948 Folder destination = dao.getEntityById(Folder.class, destId);
949 User user = dao.getEntityById(User.class, userId);
950 if (!destination.hasWritePermission(user) || !folder.hasReadPermission(user))
951 throw new InsufficientPermissionsException("You don't have the necessary permissions");
952 createFolder(user.getId(), destination.getId(), destName);
956 public void copyFolderStructureToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
958 throw new ObjectNotFoundException("No user specified");
960 throw new ObjectNotFoundException("No owner specified");
961 if (folderId == null)
962 throw new ObjectNotFoundException("No folder specified");
963 if (StringUtils.isEmpty(dest))
964 throw new ObjectNotFoundException("No destination specified");
966 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
967 if (!(destination instanceof FolderDTO))
968 throw new ObjectNotFoundException("Destination folder not found");
969 FolderDTO parent = (FolderDTO) destination;
970 copyFolderStructure(userId, folderId, parent.getId(), getLastElement(dest));
974 public void copyFolderStructure(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
976 throw new ObjectNotFoundException("No user specified");
977 if (folderId == null)
978 throw new ObjectNotFoundException("No folder specified");
980 throw new ObjectNotFoundException("No destination specified");
981 if (StringUtils.isEmpty(destName))
982 throw new ObjectNotFoundException("No destination folder name specified");
984 Folder folder = dao.getEntityById(Folder.class, folderId);
985 Folder destination = dao.getEntityById(Folder.class, destId);
986 final User user = dao.getEntityById(User.class, userId);
987 // XXX: quick fix need to copy only visible items to user (Source
989 if (!folder.getOwner().getId().equals(userId) && !folder.hasReadPermission(user))
991 if(folder.isDeleted())//do not copy trashed folder and contents
993 if (!destination.hasWritePermission(user) || !folder.hasReadPermission(user))
994 throw new InsufficientPermissionsException("You don't have the necessary permissions");
995 createFolder(user.getId(), destination.getId(), destName);
996 Folder createdFolder = dao.getFolder(destination.getId(), destName);
997 List<FileHeader> files = folder.getFiles();
999 for (FileHeader file : files)
1000 if(!file.isDeleted())
1001 copyFile(userId, file.getId(), createdFolder.getId(), file.getName());
1002 List<Folder> subFolders = folder.getSubfolders();
1003 if (subFolders != null)
1004 for (Folder sub : subFolders)
1005 if(!sub.getId().equals(createdFolder.getId()))
1006 copyFolderStructure(userId, sub.getId(), createdFolder.getId(), sub.getName());
1011 * For a provided path, remove the last element and return the rest, that is
1012 * the path of the parent folder.
1014 * @param path the specified path
1015 * @return the path of the parent folder
1016 * @throws ObjectNotFoundException if the provided string contains no path
1019 private String getParentPath(String path) throws ObjectNotFoundException {
1020 int lastDelimiter = path.lastIndexOf('/');
1021 if (lastDelimiter == 0)
1023 if (lastDelimiter == -1)
1025 throw new ObjectNotFoundException("There is no parent in the path: " + path);
1026 else if (lastDelimiter < path.length() - 1)
1027 // Return the part before the delimiter.
1028 return path.substring(0, lastDelimiter);
1030 // Remove the trailing delimiter and then recurse.
1031 String strippedTrail = path.substring(0, lastDelimiter);
1032 return getParentPath(strippedTrail);
1037 * Get the last element in a path that denotes the file or folder name.
1039 * @param path the provided path
1040 * @return the last element in the path
1042 private String getLastElement(String path) {
1043 int lastDelimiter = path.lastIndexOf('/');
1044 if (lastDelimiter == -1)
1047 else if (lastDelimiter < path.length() - 1)
1048 // Return the part after the delimiter.
1049 return path.substring(lastDelimiter + 1);
1051 // Remove the trailing delimiter and then recurse.
1052 String strippedTrail = path.substring(0, lastDelimiter);
1053 return getLastElement(strippedTrail);
1058 public void moveFileToTrash(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1060 throw new ObjectNotFoundException("No user specified");
1062 throw new ObjectNotFoundException("No file specified");
1064 // Do the actual work.
1065 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1066 Folder parent = file.getFolder();
1068 throw new ObjectNotFoundException("The specified file has no parent folder");
1069 User user = dao.getEntityById(User.class, userId);
1070 if (!file.hasDeletePermission(user))
1071 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
1073 file.setDeleted(true);
1078 public void moveFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, InsufficientPermissionsException, DuplicateNameException, GSSIOException, QuotaExceededException {
1080 throw new ObjectNotFoundException("No user specified");
1081 if (ownerId == null)
1082 throw new ObjectNotFoundException("No owner specified");
1084 throw new ObjectNotFoundException("No file specified");
1085 if (StringUtils.isEmpty(dest))
1086 throw new ObjectNotFoundException("No destination specified");
1088 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1089 if (!(destination instanceof FolderDTO))
1090 throw new ObjectNotFoundException("Destination parent folder not found");
1091 FolderDTO parent = (FolderDTO) destination;
1092 moveFile(userId, fileId, parent.getId(), getLastElement(dest));
1096 public void moveFile(Long userId, Long fileId, Long destId, String destName) throws InsufficientPermissionsException, ObjectNotFoundException, DuplicateNameException, GSSIOException, QuotaExceededException {
1098 throw new ObjectNotFoundException("No user specified");
1100 throw new ObjectNotFoundException("No file specified");
1102 throw new ObjectNotFoundException("No destination specified");
1103 if (StringUtils.isEmpty(destName))
1104 throw new ObjectNotFoundException("No destination file name specified");
1106 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1107 Folder destination = dao.getEntityById(Folder.class, destId);
1109 User owner = dao.getEntityById(User.class, userId);
1110 if (!file.hasDeletePermission(owner) || !destination.hasWritePermission(owner))
1111 throw new InsufficientPermissionsException("User " + owner.getId() + " cannot move file " + file.getName() + "(" + file.getId() + ")");
1112 FileBody body = file.getCurrentBody();
1113 assert body != null;
1114 File contents = new File(body.getStoredFilePath());
1116 createFile(owner.getId(), destination.getId(), destName, body.getMimeType(), new FileInputStream(contents));
1117 } catch (FileNotFoundException e) {
1118 throw new ObjectNotFoundException("File contents not found for file " + body.getStoredFilePath());
1120 deleteFile(userId, fileId);
1125 public void moveFolderToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1127 throw new ObjectNotFoundException("No user specified");
1128 if (ownerId == null)
1129 throw new ObjectNotFoundException("No owner specified");
1130 if (folderId == null)
1131 throw new ObjectNotFoundException("No folder specified");
1132 if (StringUtils.isEmpty(dest))
1133 throw new ObjectNotFoundException("No destination specified");
1135 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1136 if (!(destination instanceof FolderDTO))
1137 throw new ObjectNotFoundException("Destination parent folder not found");
1138 FolderDTO parent = (FolderDTO) destination;
1139 moveFolder(userId, folderId, parent.getId(), getLastElement(dest));
1143 public void moveFolder(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1144 // TODO Simple Move and delete of original folder, in production
1145 // scenario we must first check individual files and folders permissions
1146 copyFolderStructure(userId, folderId, destId, destName);
1147 deleteFolder(userId, folderId);
1151 * @see gr.ebs.gss.server.ejb.ExternalAPI#getDeletedFiles(java.lang.Long)
1153 public List<FileHeaderDTO> getDeletedFiles(Long userId) throws ObjectNotFoundException {
1156 throw new ObjectNotFoundException("No user specified");
1158 // Do the actual work.
1159 final List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1160 final List<FileHeader> files = dao.getDeletedFiles(userId);
1161 for (final FileHeader f : files)
1162 result.add(f.getDTO());
1167 public void removeFileFromTrash(Long userId, Long fileId)
1168 throws ObjectNotFoundException, InsufficientPermissionsException {
1170 throw new ObjectNotFoundException("No user specified");
1172 throw new ObjectNotFoundException("No file specified");
1174 // Do the actual work.
1175 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1176 Folder parent = file.getFolder();
1178 throw new ObjectNotFoundException("The specified file has no parent folder");
1179 User user = dao.getEntityById(User.class, userId);
1180 if (!file.hasDeletePermission(user))
1181 throw new InsufficientPermissionsException("User " + user.getUsername() +
1182 " cannot restore file " + file.getName());
1184 file.setDeleted(false);
1189 public void moveFolderToTrash(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
1191 throw new ObjectNotFoundException("No user specified");
1192 if (folderId == null)
1193 throw new ObjectNotFoundException("No folder specified");
1194 Folder folder = dao.getEntityById(Folder.class, folderId);
1195 User user = dao.getEntityById(User.class, userId);
1196 if (!folder.hasDeletePermission(user))
1197 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1198 folder.setDeleted(true);
1200 for (FileHeader file : folder.getFiles())
1201 moveFileToTrash(userId, file.getId());
1202 for (Folder subFolder : folder.getSubfolders())
1203 moveFolderToTrash(userId, subFolder.getId());
1208 public void removeFolderFromTrash(Long userId, Long folderId)
1209 throws ObjectNotFoundException, InsufficientPermissionsException {
1211 throw new ObjectNotFoundException("No user specified");
1212 if (folderId == null)
1213 throw new ObjectNotFoundException("No folder specified");
1214 Folder folder = dao.getEntityById(Folder.class, folderId);
1215 User user = dao.getEntityById(User.class, userId);
1216 if (!folder.hasDeletePermission(user))
1217 throw new InsufficientPermissionsException("User " + user.getUsername() +
1218 " cannot restore folder " + folder.getName());
1219 folder.setDeleted(false);
1220 for (FileHeader file : folder.getFiles())
1221 removeFileFromTrash(userId, file.getId());
1222 for (Folder subFolder : folder.getSubfolders())
1223 removeFolderFromTrash(userId, subFolder.getId());
1228 public List<FolderDTO> getDeletedRootFolders(Long userId) throws ObjectNotFoundException {
1229 List<Folder> folders = dao.getDeletedRootFolders(userId);
1230 List<FolderDTO> result = new ArrayList<FolderDTO>();
1231 for (Folder folder : folders)
1232 result.add(folder.getDTO());
1237 public void emptyTrash(Long userId) throws ObjectNotFoundException, InsufficientPermissionsException {
1238 List<FolderDTO> deletedRootFolders = getDeletedRootFolders(userId);
1239 for (FolderDTO fdto : deletedRootFolders)
1240 deleteFolder(userId, fdto.getId());
1241 List<FileHeaderDTO> deletedFiles = getDeletedFiles(userId);
1242 for (FileHeaderDTO filedto : deletedFiles)
1243 deleteFile(userId, filedto.getId());
1247 public void restoreTrash(Long userId) throws ObjectNotFoundException, InsufficientPermissionsException {
1248 List<FolderDTO> deletedRootFolders = getDeletedRootFolders(userId);
1249 for (FolderDTO fdto : deletedRootFolders)
1250 removeFolderFromTrash(userId, fdto.getId());
1251 List<FileHeaderDTO> deletedFiles = getDeletedFiles(userId);
1252 for (FileHeaderDTO filedto : deletedFiles)
1253 removeFileFromTrash(userId, filedto.getId());
1257 public User createUser(String username, String name, String mail) throws ObjectNotFoundException {
1258 if (username == null)
1259 throw new ObjectNotFoundException("No username specified");
1261 throw new ObjectNotFoundException("No name specified");
1263 User user = new User();
1264 user.setUsername(username);
1266 user.setEmail(mail);
1267 Date now = new Date();
1268 AuditInfo auditInfo = new AuditInfo();
1269 auditInfo.setCreationDate(now);
1270 auditInfo.setModificationDate(now);
1271 user.setAuditInfo(auditInfo);
1272 user.generateAuthToken();
1274 // Make sure we get an ID in the user object.
1276 // Create the root folder for the user.
1277 createFolder(user.getName(), null, user);
1282 public User findUserByEmail(String email) {
1283 return dao.findUserByEmail(email);
1287 public void updateUser(User user) {
1292 public User updateUser(String username, String name, String mail) throws ObjectNotFoundException {
1293 if (username == null)
1294 throw new ObjectNotFoundException("No username specified");
1296 User user = dao.getUser(username);
1298 user.setEmail(mail);
1303 public User findUser(String username) {
1304 if (username == null)
1306 return dao.findUser(username);
1310 public User updateUserToken(Long userId) throws ObjectNotFoundException {
1312 throw new ObjectNotFoundException("No user specified");
1313 User user = dao.getEntityById(User.class, userId);
1314 user.generateAuthToken();
1319 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFolderPermissions(java.lang.Long, java.lang.Long)
1322 public Set<PermissionDTO> getFolderPermissions(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
1324 throw new ObjectNotFoundException("No user specified");
1325 if (folderId == null)
1326 throw new ObjectNotFoundException("No folder specified");
1327 User user = dao.getEntityById(User.class, userId);
1328 Folder folder = dao.getEntityById(Folder.class, folderId);
1329 if(!folder.hasReadPermission(user))
1330 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1331 Set<Permission> perms = folder.getPermissions();
1332 Set<PermissionDTO> result = new LinkedHashSet<PermissionDTO>();
1333 for (Permission perm : perms)
1334 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId()))
1335 result.add(perm.getDTO());
1336 for (Permission perm : perms)
1337 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId())) {
1339 result.add(perm.getDTO());
1345 * @see gr.ebs.gss.server.ejb.ExternalAPI#setFolderPermissions(java.lang.Long, java.lang.Long, java.util.Set)
1348 public void setFolderPermissions(Long userId, Long folderId, Set<PermissionDTO> permissions) throws ObjectNotFoundException, InsufficientPermissionsException {
1350 throw new ObjectNotFoundException("No user specified");
1351 if (folderId == null)
1352 throw new ObjectNotFoundException("No folder specified");
1353 User user = dao.getEntityById(User.class, userId);
1354 Folder folder = dao.getEntityById(Folder.class, folderId);
1355 if(!folder.hasModifyACLPermission(user))
1356 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1357 folder.getPermissions().clear();
1358 for (PermissionDTO dto : permissions)
1359 folder.addPermission(getPermission(dto));
1361 for (FileHeader fh : folder.getFiles())
1362 setFilePermissions(userId, fh.getId(), fh.isReadForAll(), permissions);
1363 for (Folder sub : folder.getSubfolders())
1364 setFolderPermissions(userId, sub.getId(), permissions);
1367 private Permission getPermission(PermissionDTO dto) throws ObjectNotFoundException {
1368 Permission res = new Permission();
1369 if (dto.getGroup() != null)
1370 res.setGroup(dao.getEntityById(Group.class, dto.getGroup().getId()));
1371 else if (dto.getUser() != null)
1372 if (dto.getUser().getId() == null)
1373 res.setUser(dao.getUser(dto.getUser().getUsername()));
1375 res.setUser(dao.getEntityById(User.class, dto.getUser().getId()));
1376 res.setRead(dto.hasRead());
1377 res.setWrite(dto.hasWrite());
1378 res.setModifyACL(dto.hasModifyACL());
1383 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsersByUserNameLike(java.lang.String)
1386 public List<UserDTO> getUsersByUserNameLike(String username) {
1387 List<User> users = dao.getUsersByUserNameLike(username);
1388 List<UserDTO> result = new ArrayList<UserDTO>();
1389 for (User u : users)
1390 result.add(u.getDTO());
1396 * @see gr.ebs.gss.server.ejb.ExternalAPI#addUserToGroup(java.lang.Long, java.lang.Long, java.lang.Long)
1399 public void addUserToGroup(Long userId, Long groupId, Long userToAddId) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
1401 throw new ObjectNotFoundException("No user specified");
1402 if (groupId == null)
1403 throw new ObjectNotFoundException("No group specified");
1404 if (userToAddId == null)
1405 throw new ObjectNotFoundException("No user to add specified");
1406 User user = dao.getEntityById(User.class, userId);
1407 Group group = dao.getEntityById(Group.class, groupId);
1408 if (!group.getOwner().equals(user))
1409 throw new InsufficientPermissionsException();
1410 User userToAdd = dao.getEntityById(User.class, userToAddId);
1411 if (group.contains(userToAdd))
1412 throw new DuplicateNameException("User already exists in group");
1413 group.getMembers().add(userToAdd);
1419 public void invalidateUserToken(Long userId) throws ObjectNotFoundException {
1421 throw new ObjectNotFoundException("No user specified");
1422 User user = dao.getEntityById(User.class, userId);
1423 user.invalidateAuthToken();
1428 public List<FolderDTO> getSharedRootFolders(Long userId) throws ObjectNotFoundException {
1430 throw new ObjectNotFoundException("No user specified");
1431 List<Folder> folders = dao.getSharedRootFolders(userId);
1432 List<FolderDTO> result = new ArrayList<FolderDTO>();
1433 for (Folder f : folders) {
1434 FolderDTO dto = f.getDTO();
1435 dto.setSubfolders(getSharedSubfolders(userId, f.getId()));
1442 * @see gr.ebs.gss.server.ejb.ExternalAPI#removeMemberFromGroup(java.lang.Long, java.lang.Long, java.lang.Long)
1445 public void removeMemberFromGroup(Long userId, Long groupId, Long memberId) throws ObjectNotFoundException, InsufficientPermissionsException {
1447 throw new ObjectNotFoundException("No user specified");
1448 if (groupId == null)
1449 throw new ObjectNotFoundException("No group specified");
1450 if (memberId == null)
1451 throw new ObjectNotFoundException("No member specified");
1452 User owner = dao.getEntityById(User.class, userId);
1453 Group group = dao.getEntityById(Group.class, groupId);
1454 User member = dao.getEntityById(User.class, memberId);
1455 if (!group.getOwner().equals(owner))
1456 throw new InsufficientPermissionsException("User is not the owner of the group");
1457 group.removeMemberFromGroup(member);
1463 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsersSharingFoldersForUser(java.lang.Long)
1466 public List<UserDTO> getUsersSharingFoldersForUser(Long userId) throws ObjectNotFoundException {
1467 List<User> users = dao.getUsersSharingFoldersForUser(userId);
1468 List<User> usersFiles = dao.getUsersSharingFilesForUser(userId);
1469 List<UserDTO> res = new ArrayList<UserDTO>();
1470 for (User u : users)
1471 res.add(u.getDTO());
1472 for(User fu : usersFiles)
1473 if(!users.contains(fu))
1474 res.add(fu.getDTO());
1479 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFilePermissions(java.lang.Long, java.lang.Long)
1482 public Set<PermissionDTO> getFilePermissions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1484 throw new ObjectNotFoundException("No user specified");
1486 throw new ObjectNotFoundException("No folder specified");
1487 User user = dao.getEntityById(User.class, userId);
1488 FileHeader folder = dao.getEntityById(FileHeader.class, fileId);
1489 if(!folder.hasReadPermission(user))
1490 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1491 Set<Permission> perms = folder.getPermissions();
1492 Set<PermissionDTO> result = new LinkedHashSet<PermissionDTO>();
1493 for (Permission perm : perms)
1494 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId()))
1495 result.add(perm.getDTO());
1496 for (Permission perm : perms)
1497 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId())) {
1499 result.add(perm.getDTO());
1504 public void setFilePermissions(Long userId, Long fileId, Boolean readForAll, Set<PermissionDTO> permissions) throws ObjectNotFoundException, InsufficientPermissionsException {
1506 throw new ObjectNotFoundException("No user specified");
1508 throw new ObjectNotFoundException("No folder specified");
1510 User user = dao.getEntityById(User.class, userId);
1511 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1512 if(!file.hasModifyACLPermission(user))
1513 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1515 if (readForAll != null)
1516 if (user.equals(file.getOwner()))
1517 file.setReadForAll(readForAll);
1519 throw new InsufficientPermissionsException("Only the owner can change the read-for-all flag");
1521 if (permissions != null && !permissions.isEmpty()) {
1522 file.getPermissions().clear();
1523 for (PermissionDTO dto : permissions)
1524 file.addPermission(getPermission(dto));
1527 // Update the file if there was a change.
1528 if (readForAll != null || permissions != null && !permissions.isEmpty())
1534 public List<FileHeaderDTO> getSharedFilesNotInSharedFolders(Long userId) throws ObjectNotFoundException {
1536 throw new ObjectNotFoundException("No user specified");
1537 List<FileHeader> files = dao.getSharedFilesNotInSharedFolders(userId);
1538 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1539 for (FileHeader f : files)
1540 result.add(f.getDTO());
1545 public List<FileHeaderDTO> getSharedFiles(Long userId) throws ObjectNotFoundException {
1547 throw new ObjectNotFoundException("No user specified");
1548 List<FileHeader> files = dao.getSharedFiles(userId);
1549 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1550 for (FileHeader f : files)
1551 result.add(f.getDTO());
1556 public List<FolderDTO> getSharedFolders(Long userId) throws ObjectNotFoundException {
1558 throw new ObjectNotFoundException("No user specified");
1559 List<Folder> folders = dao.getSharedFolders(userId);
1560 List<FolderDTO> result = new ArrayList<FolderDTO>();
1561 for (Folder f : folders)
1562 result.add(f.getDTO());
1567 * @see gr.ebs.gss.server.ejb.ExternalAPI#getSharedFiles(java.lang.Long, java.lang.Long)
1570 public List<FileHeaderDTO> getSharedFiles(Long ownerId, Long callingUserId) throws ObjectNotFoundException {
1571 if (ownerId == null)
1572 throw new ObjectNotFoundException("No owner specified");
1573 if (callingUserId == null)
1574 throw new ObjectNotFoundException("No calling user specified");
1575 List<FileHeader> folders = dao.getSharedFiles(ownerId, callingUserId);
1576 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1577 for (FileHeader f : folders)
1578 result.add(f.getDTO());
1583 public List<FolderDTO> getSharedRootFolders(Long ownerId, Long callingUserId) throws ObjectNotFoundException {
1584 if (ownerId == null)
1585 throw new ObjectNotFoundException("No owner specified");
1586 if (callingUserId == null)
1587 throw new ObjectNotFoundException("No calling user specified");
1588 List<Folder> folders = dao.getSharedRootFolders(ownerId, callingUserId);
1589 List<FolderDTO> result = new ArrayList<FolderDTO>();
1590 for (Folder f : folders) {
1591 FolderDTO dto = f.getDTO();
1592 dto.setSubfolders(getSharedSubfolders(ownerId, callingUserId, f.getId()));
1600 public List<FolderDTO> getSharedSubfolders(Long userId, Long folderId) throws ObjectNotFoundException {
1602 throw new ObjectNotFoundException("No user specified");
1603 if (folderId == null)
1604 throw new ObjectNotFoundException("No folder specified");
1605 User user = dao.getEntityById(User.class, userId);
1606 Folder folder = dao.getEntityById(Folder.class, folderId);
1607 List<FolderDTO> result = new ArrayList<FolderDTO>();
1608 if (folder.isShared(user))
1609 for (Folder f : folder.getSubfolders())
1610 if (f.isShared(user) && !f.isDeleted())
1611 result.add(f.getDTO());
1616 public List<FolderDTO> getSharedSubfolders(Long userId, Long callingUserId, Long folderId) throws ObjectNotFoundException {
1618 throw new ObjectNotFoundException("No user specified");
1619 if (callingUserId == null)
1620 throw new ObjectNotFoundException("No user specified");
1621 if (folderId == null)
1622 throw new ObjectNotFoundException("No folder specified");
1623 User user = dao.getEntityById(User.class, callingUserId);
1624 Folder folder = dao.getEntityById(Folder.class, folderId);
1625 List<FolderDTO> result = new ArrayList<FolderDTO>();
1626 if (folder.isSharedForOtherUser(user))
1627 for (Folder f : folder.getSubfolders())
1628 if (f.isSharedForOtherUser(user) && !f.isDeleted()){
1629 FolderDTO dto = f.getDTO();
1630 dto.setSubfolders(getSharedSubfolders(userId, callingUserId, dto.getId()));
1638 * @see gr.ebs.gss.server.ejb.ExternalAPI#searchFiles(java.lang.Long, java.lang.String)
1641 public List<FileHeaderDTO> searchFiles(Long userId, String query) throws ObjectNotFoundException {
1643 throw new ObjectNotFoundException("No user specified");
1644 User user = getUser(userId);
1646 throw new ObjectNotFoundException("No query specified");
1647 List<FileHeader> files = search(user.getId(), query);
1648 List<FileHeaderDTO> res = new ArrayList<FileHeaderDTO>();
1649 for(FileHeader f : files)
1650 res.add(f.getDTO());
1655 * Performs the actuals search on the solr server and returns the results
1657 * We have to use the dismax query type (instead of the
1658 * standard) because it allows for search time field boosting. This is because we can't use indexing
1659 * time field boosting due to the patched rich indexing API that does not allow it
1663 * @return a List of FileHeader objects
1665 private List<FileHeader> search(Long userId, String query) {
1667 HttpClient httpClient = new HttpClient();
1669 GetMethod method = new GetMethod(conf.getString("solrSelectUrl"));
1670 NameValuePair[] params = {new NameValuePair("qt", "dismax"),
1671 new NameValuePair("q", query),
1672 new NameValuePair("sort", "score desc"),
1673 new NameValuePair("indent", "on")};
1674 method.setQueryString(params);
1677 String response = null;
1679 statusCode = httpClient.executeMethod(method);
1680 logger.debug("HTTP status: " + statusCode);
1681 response = method.getResponseBodyAsString();
1682 logger.debug(response);
1684 if (statusCode != 200 && retryCount < 3)
1686 Thread.sleep(3000); //Give Solr a little time to be available
1687 } catch (InterruptedException e) {
1689 } while (statusCode != 200 && retryCount < 3);
1690 if (statusCode != 200)
1691 throw new EJBException("Search query return error:\n" + response);
1693 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
1694 DocumentBuilder db = dbf.newDocumentBuilder();
1695 Document doc = db.parse(method.getResponseBodyAsStream());
1696 method.releaseConnection();
1698 Node root = doc.getElementsByTagName("response").item(0);
1699 Node lst = root.getFirstChild().getNextSibling();
1700 Node status = lst.getFirstChild().getNextSibling();
1701 if (status.getAttributes().getNamedItem("name").getNodeValue().equals("status") &&
1702 status.getTextContent().equals("0")) {
1703 List<FileHeader> fileResult = new ArrayList<FileHeader>();
1704 Node result = lst.getNextSibling().getNextSibling();
1705 NodeList docs = result.getChildNodes();
1706 User user = getUser(userId);
1707 for (int i=1; i<docs.getLength(); i=i+2) {
1708 Node d = docs.item(i);
1709 NodeList docData = d.getChildNodes();
1710 for (int j=1; j<docData.getLength(); j=j+2) {
1711 Node dd = docData.item(j);
1712 if (dd.getAttributes().item(0).getNodeName().equals("name") &&
1713 dd.getAttributes().item(0).getNodeValue().equals("id")) {
1714 Long fileId = Long.valueOf(dd.getTextContent());
1716 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1717 if (file.hasReadPermission(user)) {
1718 fileResult.add(file);
1719 logger.debug("File added " + fileId);
1721 } catch (ObjectNotFoundException e) {
1722 logger.warn("Search result not found", e);
1729 throw new EJBException();
1730 } catch (HttpException e) {
1731 throw new EJBException(e);
1732 } catch (IOException e) {
1733 throw new EJBException(e);
1734 } catch (SAXException e) {
1735 throw new EJBException(e);
1736 } catch (ParserConfigurationException e) {
1737 throw new EJBException(e);
1738 } catch (ObjectNotFoundException e) {
1739 throw new EJBException(e);
1744 * @see gr.ebs.gss.server.ejb.ExternalAPI#copyFiles(java.lang.Long, java.util.List, java.lang.Long)
1747 public void copyFiles(Long userId, List<Long> fileIds, Long destId) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
1748 for(Long l : fileIds){
1749 FileHeader file = dao.getEntityById(FileHeader.class, l);
1750 copyFile(userId, l, destId, file.getName());
1757 * @see gr.ebs.gss.server.ejb.ExternalAPI#moveFiles(java.lang.Long, java.util.List, java.lang.Long)
1760 public void moveFiles(Long userId, List<Long> fileIds, Long destId) throws InsufficientPermissionsException, ObjectNotFoundException, DuplicateNameException, GSSIOException, QuotaExceededException {
1761 for(Long l : fileIds){
1762 FileHeader file = dao.getEntityById(FileHeader.class, l);
1763 moveFile(userId, l, destId, file.getName());
1769 * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteFiles(java.lang.Long, java.util.List)
1772 public void deleteFiles(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1774 throw new ObjectNotFoundException("No user specified");
1775 final User user = dao.getEntityById(User.class, userId);
1776 List<File> filesToRemove = new ArrayList<File>();
1777 //first delete database objects
1778 for(Long fileId : fileIds){
1780 throw new ObjectNotFoundException("No file specified");
1781 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1782 final Folder parent = file.getFolder();
1784 throw new ObjectNotFoundException("The specified file has no parent folder");
1785 if (!file.hasDeletePermission(user))
1786 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
1788 parent.removeFile(file);
1789 for (final FileBody body : file.getBodies()) {
1790 final File fileContents = new File(body.getStoredFilePath());
1791 filesToRemove.add(fileContents);
1795 //then remove physical files if everything is ok
1796 for(File physicalFile : filesToRemove)
1797 if (!physicalFile.delete())
1798 logger.error("Could not delete file " + physicalFile.getPath());
1799 //then unindex deleted files
1800 for(Long fileId : fileIds)
1801 indexFile(fileId, true);
1806 * @see gr.ebs.gss.server.ejb.ExternalAPI#moveFilesToTrash(java.lang.Long, java.util.List)
1809 public void moveFilesToTrash(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1810 for(Long l : fileIds)
1811 moveFileToTrash(userId, l);
1816 public void removeFilesFromTrash(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1817 for(Long l : fileIds)
1818 removeFileFromTrash(userId, l);
1823 public Nonce createNonce(Long userId) throws ObjectNotFoundException {
1825 throw new ObjectNotFoundException("No user specified");
1826 User user = dao.getEntityById(User.class, userId);
1827 Nonce nonce = Nonce.createNonce(user.getId());
1833 public Nonce getNonce(String nonce, Long userId) throws ObjectNotFoundException {
1835 throw new ObjectNotFoundException("No user specified");
1837 throw new ObjectNotFoundException("No nonce specified");
1838 return dao.getNonce(nonce, userId);
1842 public void removeNonce(Long id) throws ObjectNotFoundException {
1844 throw new ObjectNotFoundException("No nonce specified");
1845 Nonce nonce = dao.getEntityById(Nonce.class, id);
1850 public void activateUserNonce(Long userId, String nonce, Date nonceExpiryDate) throws ObjectNotFoundException {
1852 throw new ObjectNotFoundException("No user specified");
1853 User user = dao.getEntityById(User.class, userId);
1854 user.setNonce(nonce);
1855 user.setNonceExpiryDate(nonceExpiryDate);
1859 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUserStatistics(java.lang.Long)
1862 public StatsDTO getUserStatistics(Long userId) throws ObjectNotFoundException {
1864 throw new ObjectNotFoundException("No user specified");
1865 StatsDTO stats = new StatsDTO();
1866 stats.setFileCount(dao.getFileCount(userId));
1867 Long fileSize = dao.getFileSize(userId);
1868 stats.setFileSize(fileSize);
1869 Long quota = conf.getLong("quota", new Long(52428800L));
1870 Long quotaLeft = quota - fileSize;
1871 stats.setQuotaLeftSize(quotaLeft);
1876 * @see gr.ebs.gss.server.ejb.ExternalAPI#getVersions(java.lang.Long, java.lang.Long)
1879 public List<FileBodyDTO> getVersions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1881 throw new ObjectNotFoundException("No user specified");
1883 throw new ObjectNotFoundException("No file specified");
1884 User user = dao.getEntityById(User.class, userId);
1885 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
1886 if(!header.hasReadPermission(user))
1887 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1888 List<FileBodyDTO> result = new LinkedList<FileBodyDTO>();
1889 for(int i = header.getBodies().size()-1 ; i>=0; i--)
1890 result.add(header.getBodies().get(i).getDTO());
1895 * @see gr.ebs.gss.server.ejb.ExternalAPI#removeVersion(java.lang.Long, java.lang.Long, java.lang.Long)
1898 public void removeVersion(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
1900 throw new ObjectNotFoundException("No user specified");
1902 throw new ObjectNotFoundException("No file specified");
1904 throw new ObjectNotFoundException("No body specified");
1905 User user = dao.getEntityById(User.class, userId);
1906 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
1907 if(!header.hasWritePermission(user))
1908 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1909 FileBody body = dao.getEntityById(FileBody.class, bodyId);
1910 if(body.equals(header.getCurrentBody())){
1912 if(header.getBodies().size() == 1)
1913 throw new InsufficientPermissionsException("You cant delete this version, Delete file instead!");
1914 for(FileBody b : header.getBodies())
1915 if(b.getVersion() == body.getVersion()-1)
1916 header.setCurrentBody(b);
1918 final File fileContents = new File(body.getStoredFilePath());
1919 if (!fileContents.delete())
1920 logger.error("Could not delete file " + body.getStoredFilePath());
1921 header.getBodies().remove(body);
1927 public void restoreVersion(Long userId, Long fileId, int version) throws ObjectNotFoundException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1929 throw new ObjectNotFoundException("No user specified");
1931 throw new ObjectNotFoundException("No file specified");
1932 User user = dao.getEntityById(User.class, userId);
1933 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
1934 if(!header.hasWritePermission(user))
1935 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1936 FileBody body = dao.getFileVersion(fileId, version);
1937 final File fileContents = new File(body.getStoredFilePath());
1940 updateFileContents(userId, fileId, body.getMimeType(), new FileInputStream(fileContents) );
1941 } catch (FileNotFoundException e) {
1942 throw new GSSIOException(e);
1948 * @see gr.ebs.gss.server.ejb.ExternalAPI#removeOldVersions(java.lang.Long, java.lang.Long)
1951 public void removeOldVersions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1953 throw new ObjectNotFoundException("No user specified");
1955 throw new ObjectNotFoundException("No file specified");
1956 User user = dao.getEntityById(User.class, userId);
1957 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
1958 if(!header.hasWritePermission(user))
1959 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1960 Iterator<FileBody> it = header.getBodies().iterator();
1961 while(it.hasNext()){
1962 FileBody body = it.next();
1963 if(!body.equals(header.getCurrentBody())){
1964 final File fileContents = new File(body.getStoredFilePath());
1965 if (!fileContents.delete())
1966 logger.error("Could not delete file " + body.getStoredFilePath());
1971 header.getCurrentBody().setVersion(1);
1976 * @see gr.ebs.gss.server.ejb.ExternalAPI#toggleFileVersioning(java.lang.Long, java.lang.Long, boolean)
1979 public void toggleFileVersioning(Long userId, Long fileId, boolean versioned) throws ObjectNotFoundException, InsufficientPermissionsException {
1981 throw new ObjectNotFoundException("No user specified");
1983 throw new ObjectNotFoundException("No file specified");
1984 User user = dao.getEntityById(User.class, userId);
1985 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
1986 if(!header.hasWritePermission(user))
1987 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1988 if(!header.isVersioned() == versioned){
1989 if(header.isVersioned())
1990 removeOldVersions(userId, fileId);
1991 header.setVersioned(versioned);
1997 * Gets the quota left for specified userId
2001 private Long getQuotaLeft(Long userId){
2002 Long fileSize = dao.getFileSize(userId);
2003 Long quota = conf.getLong("quota", new Long(52428800L));
2004 return quota - fileSize;
2007 public void rebuildSolrIndex() {
2008 MessageProducer sender = null;
2009 Session session = null;
2010 Connection qConn = null;
2012 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
2013 DocumentBuilder db = dbf.newDocumentBuilder();
2014 Document doc = db.newDocument();
2015 Node root = doc.createElement("delete");
2016 doc.appendChild(root);
2017 Node queryNode = doc.createElement("query");
2018 root.appendChild(queryNode);
2019 queryNode.appendChild(doc.createTextNode("*:*"));
2021 TransformerFactory fact = TransformerFactory.newInstance();
2022 Transformer trans = fact.newTransformer();
2023 trans.setOutputProperty(OutputKeys.INDENT, "yes");
2024 StringWriter sw = new StringWriter();
2025 StreamResult sr = new StreamResult(sw);
2026 DOMSource source = new DOMSource(doc);
2027 trans.transform(source, sr);
2028 logger.debug(sw.toString());
2030 HttpClient httpClient = new HttpClient();
2031 PostMethod method = new PostMethod(conf.getString("solrUpdateUrl"));
2032 method.setRequestEntity(new StringRequestEntity(sw.toString()));
2035 String response = null;
2037 statusCode = httpClient.executeMethod(method);
2038 logger.debug("HTTP status: " + statusCode);
2039 response = method.getResponseBodyAsString();
2040 logger.debug(response);
2042 if (statusCode != 200 && retryCount < 3)
2044 Thread.sleep(10000); //Give Solr a little time to be available
2045 } catch (InterruptedException e) {
2047 } while (statusCode != 200 && retryCount < 3);
2048 method.releaseConnection();
2049 if (statusCode != 200)
2050 throw new EJBException("Cannot clear Solr index. Solr response is:\n" + response);
2051 List<Long> fileIds = dao.getAllFileIds();
2053 Context jndiCtx = new InitialContext();
2054 ConnectionFactory factory = (QueueConnectionFactory) jndiCtx.lookup("java:/JmsXA");
2055 Queue queue = (Queue) jndiCtx.lookup("queue/gss-indexingQueue");
2056 qConn = factory.createConnection();
2057 session = qConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
2058 sender = session.createProducer(queue);
2060 for (Long id : fileIds) {
2061 MapMessage map = session.createMapMessage();
2062 map.setObject("id", id);
2063 map.setBoolean("delete", false);
2066 sendOptimize(httpClient, 0);
2067 } catch (DOMException e) {
2068 throw new EJBException(e);
2069 } catch (TransformerConfigurationException e) {
2070 throw new EJBException(e);
2071 } catch (IllegalArgumentException e) {
2072 throw new EJBException(e);
2073 } catch (HttpException e) {
2074 throw new EJBException(e);
2075 } catch (UnsupportedEncodingException e) {
2076 throw new EJBException(e);
2077 } catch (ParserConfigurationException e) {
2078 throw new EJBException(e);
2079 } catch (TransformerException e) {
2080 throw new EJBException(e);
2081 } catch (IOException e) {
2082 throw new EJBException(e);
2083 } catch (NamingException e) {
2084 throw new EJBException(e);
2085 } catch (JMSException e) {
2086 throw new EJBException(e);
2092 if (session != null)
2097 catch (JMSException e) {
2104 * Sends a optimize message to the solr server
2107 * @param retryCount If the commit fails, it is retried three times. This parameter is passed in the recursive
2108 * calls to stop the recursion
2109 * @throws UnsupportedEncodingException
2110 * @throws IOException
2111 * @throws HttpException
2113 private void sendOptimize(HttpClient httpClient, int retryCount) throws UnsupportedEncodingException, IOException, HttpException {
2114 PostMethod method = null;
2116 logger.debug("Optimize retry: " + retryCount);
2117 method = new PostMethod(conf.getString("solrUpdateUrl"));
2118 method.setRequestEntity(new StringRequestEntity("<optimize/>", "text/xml", "iso8859-1"));
2119 int statusCode = httpClient.executeMethod(method);
2120 logger.debug("HTTP status: " + statusCode);
2121 String response = method.getResponseBodyAsString();
2122 logger.debug(response);
2123 if (statusCode != 200 && retryCount < 2) {
2125 Thread.sleep(10000); //Give Solr a little time to be available
2126 } catch (InterruptedException e) {
2128 sendOptimize(httpClient, retryCount + 1);
2133 method.releaseConnection();
2137 public void createFile(Long userId, Long folderId, String name, String mimeType, File fileObject)
2138 throws DuplicateNameException, ObjectNotFoundException, GSSIOException,
2139 InsufficientPermissionsException, QuotaExceededException {
2142 throw new ObjectNotFoundException("No user specified");
2143 if (folderId == null)
2144 throw new ObjectNotFoundException("No folder specified");
2145 String contentType = mimeType;
2146 if (StringUtils.isEmpty(mimeType))
2147 contentType = DEFAULT_MIME_TYPE;
2148 if (StringUtils.isEmpty(name))
2149 throw new ObjectNotFoundException("No file name specified");
2150 if (dao.existsFolderOrFile(folderId, name))
2151 throw new DuplicateNameException("A folder or file with the name '" + name +
2152 "' already exists at this level");
2154 // Do the actual work.
2155 Folder parent = null;
2157 parent = dao.getEntityById(Folder.class, folderId);
2158 } catch (final ObjectNotFoundException onfe) {
2159 // Supply a more accurate problem description.
2160 throw new ObjectNotFoundException("Parent folder not found");
2162 final User owner = dao.getEntityById(User.class, userId);
2163 if (!parent.hasWritePermission(owner))
2164 throw new InsufficientPermissionsException("You don't have the permissions to write to this folder");
2165 final FileHeader file = new FileHeader();
2167 parent.addFile(file);
2168 // set file owner to folder owner
2169 file.setOwner(parent.getOwner());
2171 final Date now = new Date();
2172 final AuditInfo auditInfo = new AuditInfo();
2173 auditInfo.setCreatedBy(owner);
2174 auditInfo.setCreationDate(now);
2175 auditInfo.setModifiedBy(owner);
2176 auditInfo.setModificationDate(now);
2177 file.setAuditInfo(auditInfo);
2178 // TODO set the proper versioning flag on creation
2179 file.setVersioned(false);
2181 for (final Permission p : parent.getPermissions()) {
2182 final Permission permission = new Permission();
2183 permission.setGroup(p.getGroup());
2184 permission.setUser(p.getUser());
2185 permission.setRead(p.getRead());
2186 permission.setWrite(p.getWrite());
2187 permission.setModifyACL(p.getModifyACL());
2188 file.addPermission(permission);
2191 // Create the file body.
2193 createFileBody(name, contentType, fileObject, file, auditInfo, owner);
2194 } catch (FileNotFoundException e) {
2195 throw new GSSIOException(e);
2198 indexFile(file.getId(), false);
2202 * @see gr.ebs.gss.server.ejb.ExternalAPI#updateFileContents(java.lang.Long, java.lang.Long, java.lang.String, java.io.InputStream)
2204 public void updateFileContents(Long userId, Long fileId, String mimeType, File fileObject) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
2206 throw new ObjectNotFoundException("No user specified");
2208 throw new ObjectNotFoundException("No file specified");
2209 String contentType = mimeType;
2211 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
2213 // if no mime type or the generic mime type is defined by the client, then try to identify it from the filename extension
2214 if (StringUtils.isEmpty(mimeType) || "application/octet-stream".equals(mimeType))
2215 contentType = identifyMimeType(file.getName());
2217 final User owner = dao.getEntityById(User.class, userId);
2218 if (!file.hasWritePermission(owner))
2219 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2220 final Date now = new Date();
2221 final AuditInfo auditInfo = new AuditInfo();
2222 auditInfo.setCreatedBy(owner);
2223 auditInfo.setCreationDate(now);
2224 auditInfo.setModifiedBy(owner);
2225 auditInfo.setModificationDate(now);
2227 createFileBody(file.getName(), contentType, fileObject, file, auditInfo, owner);
2228 } catch (FileNotFoundException e) {
2229 throw new GSSIOException(e);
2232 indexFile(fileId, false);
2236 * Helper method for identifying mime type by examining the filename extension
2239 * @return the mime type
2241 private String identifyMimeType(String filename) {
2242 if (filename.indexOf('.') != 1) {
2243 String extension = filename.substring(filename.lastIndexOf('.'));
2244 if (".doc".equals(extension))
2245 return "application/msword";
2246 else if (".xls".equals(extension))
2247 return "application/vnd.ms-excel";
2248 else if (".ppt".equals(extension))
2249 return "application/vnd.ms-powerpoint";
2250 else if (".pdf".equals(extension))
2251 return "application/pdf";
2253 // when all else fails assign the default mime type
2254 return DEFAULT_MIME_TYPE;
2258 * Helper method to create a new file body and attach it as the current body
2259 * of the provided file header.
2261 * @param name the original file name
2262 * @param mimeType the content type
2263 * @param uploadedFile the uploaded file contents
2264 * @param header the file header that will be associated with the new body
2265 * @param auditInfo the audit info
2266 * @param owner the owner of the file
2267 * @throws FileNotFoundException
2268 * @throws QuotaExceededException
2270 private void createFileBody(String name, String mimeType, File uploadedFile,
2271 FileHeader header, AuditInfo auditInfo, User owner)
2272 throws FileNotFoundException, QuotaExceededException {
2273 FileBody body = new FileBody();
2275 // if no mime type or the generic mime type is defined by the client, then try to identify it from the filename extension
2276 if (StringUtils.isEmpty(mimeType) || "application/octet-stream".equals(mimeType))
2277 body.setMimeType(identifyMimeType(name));
2279 body.setMimeType(mimeType);
2280 body.setAuditInfo(auditInfo);
2281 body.setFileSize(uploadedFile.length());
2282 body.setOriginalFilename(name);
2283 body.setStoredFilePath(uploadedFile.getAbsolutePath());
2284 //CLEAR OLD VERSION IF FILE IS NOT VERSIONED AND GETS UPDATED
2285 if(!header.isVersioned() && header.getCurrentBody() != null){
2286 header.setCurrentBody(null);
2287 if (header.getBodies() != null) {
2288 Iterator<FileBody> it = header.getBodies().iterator();
2289 while(it.hasNext()){
2290 FileBody bo = it.next();
2291 File fileContents = new File(bo.getStoredFilePath());
2292 if (!fileContents.delete())
2293 logger.error("Could not delete file " + bo.getStoredFilePath());
2300 Long quotaLeft = getQuotaLeft(owner.getId());
2301 if(quotaLeft < uploadedFile.length())
2302 throw new QuotaExceededException("Not enough free space available");
2304 header.addBody(body);
2310 @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
2311 public File uploadFile(InputStream stream, Long userId) throws IOException, ObjectNotFoundException{
2313 throw new ObjectNotFoundException("No user specified");
2314 User owner = dao.getEntityById(User.class, userId);
2316 throw new ObjectNotFoundException("No user specified");
2317 long start = 0, end = 0;
2318 if (logger.isDebugEnabled())
2319 start = System.currentTimeMillis();
2320 File result = new File(generateRepositoryFilePath());
2321 final FileOutputStream output = new FileOutputStream(result);
2322 final byte[] buffer = new byte[UPLOAD_BUFFER_SIZE];
2325 while (-1 != (n = stream.read(buffer)))
2326 output.write(buffer, 0, n);
2329 if (logger.isDebugEnabled()) {
2330 end = System.currentTimeMillis();
2331 logger.debug("UPLOAD: "+(end-start));
2337 public void createFileUploadProgress(Long userId, String filename, Long bytesTransfered, Long fileSize) throws ObjectNotFoundException{
2340 throw new ObjectNotFoundException("No user specified");
2341 User user = dao.getEntityById(User.class, userId);
2342 FileUploadStatus status = dao.getFileUploadStatus(userId, filename);
2344 status = new FileUploadStatus();
2345 status.setOwner(user);
2346 status.setFilename(filename);
2347 status.setBytesUploaded(bytesTransfered);
2348 status.setFileSize(fileSize);
2352 status.setBytesUploaded(bytesTransfered);
2353 status.setFileSize(fileSize);
2359 public void removeFileUploadProgress(Long userId, String filename) throws ObjectNotFoundException{
2361 throw new ObjectNotFoundException("No user specified");
2362 FileUploadStatus status = dao.getFileUploadStatus(userId, filename);
2368 public FileUploadStatus getFileUploadStatus(Long userId, String fileName) {
2369 return dao.getFileUploadStatus(userId, fileName);
2373 public FolderDTO getFolderWithSubfolders(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
2375 throw new ObjectNotFoundException("No user specified");
2376 if (folderId == null)
2377 throw new ObjectNotFoundException("No folder specified");
2378 final User user = dao.getEntityById(User.class, userId);
2379 final Folder folder = dao.getEntityById(Folder.class, folderId);
2380 // Check permissions
2381 if (!folder.hasReadPermission(user))
2382 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
2383 List<FolderDTO> subfolders = new ArrayList<FolderDTO>();
2384 if (folder.hasReadPermission(user))
2385 for (Folder f : folder.getSubfolders())
2386 if (f.hasReadPermission(user) && !f.isDeleted())
2387 subfolders.add(f.getDTO());
2388 FolderDTO result = folder.getDTO();
2389 result.setSubfolders(subfolders);
2390 return folder.getDTO();
2394 public FolderDTO getFolderWithSubfolders(Long userId, Long callingUserId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
2396 throw new ObjectNotFoundException("No user specified");
2397 if (folderId == null)
2398 throw new ObjectNotFoundException("No folder specified");
2399 User user = dao.getEntityById(User.class, callingUserId);
2400 Folder folder = dao.getEntityById(Folder.class, folderId);
2401 // Check permissions
2402 if (!folder.hasReadPermission(user))
2403 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
2405 FolderDTO result = folder.getDTO();
2406 result.setSubfolders(getSharedSubfolders(userId, callingUserId, folder.getId()));
2411 public FileBodyDTO getFileVersion(Long userId, Long fileId, int version)
2412 throws ObjectNotFoundException, InsufficientPermissionsException {
2414 throw new ObjectNotFoundException("No user specified");
2416 throw new ObjectNotFoundException("No file specified");
2418 throw new ObjectNotFoundException("No valid version specified");
2419 User user = dao.getEntityById(User.class, userId);
2420 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
2421 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
2422 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2423 FileBody body = dao.getFileVersion(fileId, version);
2424 return body.getDTO();
2428 public User updateUserPolicyAcceptance(Long userId, boolean isAccepted) throws ObjectNotFoundException {
2430 throw new ObjectNotFoundException("No user specified");
2431 User user = dao.getEntityById(User.class, userId);
2432 user.setAcceptedPolicy(isAccepted);