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.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.httpclient.HttpClient;
92 import org.apache.commons.httpclient.HttpException;
93 import org.apache.commons.httpclient.NameValuePair;
94 import org.apache.commons.httpclient.methods.GetMethod;
95 import org.apache.commons.httpclient.methods.PostMethod;
96 import org.apache.commons.httpclient.methods.StringRequestEntity;
97 import org.apache.commons.lang.StringUtils;
98 import org.apache.commons.logging.Log;
99 import org.apache.commons.logging.LogFactory;
100 import org.w3c.dom.DOMException;
101 import org.w3c.dom.Document;
102 import org.w3c.dom.Node;
103 import org.w3c.dom.NodeList;
104 import org.xml.sax.SAXException;
107 * The concrete implementation of the ExternalAPI interface.
112 public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
114 * The default MIME type for files without an explicit one.
116 private static final String DEFAULT_MIME_TYPE = "application/octet-stream";
119 * The size of the buffer that is used to temporarily store chunks of
120 * uploaded files, while storing them to the file repository.
122 private static final int UPLOAD_BUFFER_SIZE = 1024 * 4;
127 private static Log logger = LogFactory.getLog(ExternalAPIBean.class);
130 * Injected reference to the GSSDAO data access facade.
137 * A cached random number generator for creating unique filenames.
139 private static Random random = new Random();
142 public FolderDTO getRootFolder(Long userId) throws ObjectNotFoundException {
144 throw new ObjectNotFoundException("No user specified");
145 Folder folder = dao.getRootFolder(userId);
146 return folder.getDTO();
152 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFolder(java.lang.Long)
154 public FolderDTO getFolder(final Long userId, final Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
156 throw new ObjectNotFoundException("No user specified");
157 if (folderId == null)
158 throw new ObjectNotFoundException("No folder specified");
159 final User user = dao.getEntityById(User.class, userId);
160 final Folder folder = dao.getEntityById(Folder.class, folderId);
162 if (!folder.hasReadPermission(user))
163 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
164 return folder.getDTO();
168 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUser(java.lang.Long)
170 public User getUser(Long userId) throws ObjectNotFoundException {
172 throw new ObjectNotFoundException("No user specified");
173 return dao.getEntityById(User.class, userId);
177 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUserDTO(java.lang.Long)
179 public UserDTO getUserDTO(final Long userId) throws ObjectNotFoundException {
180 return getUser(userId).getDTO();
186 * @see gr.ebs.gss.server.ejb.ExternalAPI#getGroup(java.lang.Long)
188 public GroupDTO getGroup(final Long groupId) throws ObjectNotFoundException {
190 throw new ObjectNotFoundException("No group specified");
191 final Group group = dao.getEntityById(Group.class, groupId);
192 return group.getDTO();
196 public GroupDTO getGroup(Long userId, String name) throws ObjectNotFoundException {
198 throw new ObjectNotFoundException("No user specified");
200 throw new ObjectNotFoundException("No group specified");
201 User user = dao.getEntityById(User.class, userId);
202 List<Group> groups = user.getGroupsSpecified();
203 for (Group group: groups)
204 if (group.getName().equals(name))
205 return group.getDTO();
206 throw new ObjectNotFoundException("Group " + name + " not found");
212 * @see gr.ebs.gss.server.ejb.ExternalAPI#getGroups(java.lang.Long)
214 public List<GroupDTO> getGroups(final Long userId) throws ObjectNotFoundException {
216 throw new ObjectNotFoundException("No user specified");
217 final List<Group> groups = dao.getGroups(userId);
218 final List<GroupDTO> result = new ArrayList<GroupDTO>();
219 for (final Group g : groups)
220 result.add(g.getDTO());
225 public List<FileHeaderDTO> getFiles(Long userId, Long folderId, boolean ignoreDeleted)
226 throws ObjectNotFoundException, InsufficientPermissionsException {
229 throw new ObjectNotFoundException("No user specified");
230 if (folderId == null)
231 throw new ObjectNotFoundException("No folder specified");
232 User user = dao.getEntityById(User.class, userId);
233 Folder folder = dao.getEntityById(Folder.class, folderId);
234 if (!folder.hasReadPermission(user))
235 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
236 // Do the actual work.
237 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
238 List<FileHeader> files = dao.getFiles(folderId, userId, ignoreDeleted);
239 for (FileHeader f : files)
240 result.add(f.getDTO());
247 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsers(java.lang.Long,
250 public List<UserDTO> getUsers(final Long userId, final Long groupId) throws ObjectNotFoundException {
253 throw new ObjectNotFoundException("No user specified");
255 throw new ObjectNotFoundException("No group specified");
257 // Do the actual work.
258 final List<User> users = dao.getUsers(groupId);
259 final List<UserDTO> result = new ArrayList<UserDTO>();
260 for (final User u : users)
261 result.add(u.getDTO());
266 public void createFolder(Long userId, Long parentId, String name)
267 throws DuplicateNameException, ObjectNotFoundException, InsufficientPermissionsException {
270 throw new ObjectNotFoundException("No user specified");
271 if (StringUtils.isEmpty(name))
272 throw new ObjectNotFoundException("New folder name is empty");
273 if (parentId == null)
274 throw new ObjectNotFoundException("No parent specified");
275 if (dao.existsFolderOrFile(parentId, name))
276 throw new DuplicateNameException("A folder or file with the name '" +
277 name + "' already exists at this level");
279 User creator = dao.getEntityById(User.class, userId);
281 Folder parent = null;
283 parent = dao.getEntityById(Folder.class, parentId);
284 } catch (ObjectNotFoundException onfe) {
285 // Supply a more accurate problem description.
286 throw new ObjectNotFoundException("Parent folder not found");
288 if (!parent.hasWritePermission(creator))
289 throw new InsufficientPermissionsException("You don't have the permissions" +
290 " to write to this folder");
292 // Do the actual work.
293 createFolder(name, parent, creator);
297 * 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);
345 * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteFolder(java.lang.Long,
348 public void deleteFolder(final Long userId, final Long folderId) throws InsufficientPermissionsException, ObjectNotFoundException {
351 throw new ObjectNotFoundException("No user specified");
352 if (folderId == null)
353 throw new ObjectNotFoundException("No folder specified");
355 // Do the actual work.
356 final Folder folder = dao.getEntityById(Folder.class, folderId);
357 final Folder parent = folder.getParent();
359 throw new ObjectNotFoundException("Deleting the root folder is not allowed");
360 final User user = dao.getEntityById(User.class, userId);
361 if (!folder.hasDeletePermission(user)) {
362 logger.info("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
363 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
365 parent.removeSubfolder(folder);
369 @SuppressWarnings("unchecked")
370 public List<FolderDTO> getSubfolders(Long userId, Long folderId)
371 throws ObjectNotFoundException, InsufficientPermissionsException {
373 throw new ObjectNotFoundException("No user specified");
374 if (folderId == null)
375 throw new ObjectNotFoundException("No folder specified");
376 User user = dao.getEntityById(User.class, userId);
377 Folder folder = dao.getEntityById(Folder.class, folderId);
378 if (!folder.hasReadPermission(user))
379 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
380 List<FolderDTO> result = new ArrayList<FolderDTO>();
381 if (folder.hasReadPermission(user))
382 for (Folder f : folder.getSubfolders())
383 if (f.hasReadPermission(user) && !f.isDeleted())
384 result.add(f.getDTO());
389 public void modifyFolder(Long userId, Long folderId, String folderName)
390 throws InsufficientPermissionsException, ObjectNotFoundException, DuplicateNameException {
394 throw new ObjectNotFoundException("No user specified");
395 if (folderId == null)
396 throw new ObjectNotFoundException("No folder specified");
397 if (StringUtils.isEmpty(folderName))
398 throw new ObjectNotFoundException("New folder name is empty");
400 Folder folder = dao.getEntityById(Folder.class, folderId);
401 User user = dao.getEntityById(User.class, userId);
402 if (!folder.hasWritePermission(user))
403 throw new InsufficientPermissionsException("You don't have the necessary permissions");
405 Folder parent = folder.getParent();
407 if (!folder.getName().equals(folderName) && dao.existsFolderOrFile(parent.getId(), folderName))
408 throw new DuplicateNameException("A folder or file with the name '" + folderName + "' already exists at this level");
410 // Do the actual modification.
411 folder.setName(folderName);
418 * @see gr.ebs.gss.server.ejb.ExternalAPI#createGroup(java.lang.Long,
421 public void createGroup(final Long userId, final String name) throws ObjectNotFoundException, DuplicateNameException {
424 throw new ObjectNotFoundException("No user specified");
425 if (StringUtils.isEmpty(name))
426 throw new ObjectNotFoundException("New group name is empty");
427 if (dao.existsGroup(userId, name))
428 throw new DuplicateNameException("A group with the name '" + name + "' already exists");
430 // TODO: Check permissions
432 final User owner = dao.getEntityById(User.class, userId);
434 // Do the actual work.
435 owner.createGroup(name);
441 * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteGroup(java.lang.Long,
444 public void deleteGroup(final Long userId, final Long groupId) throws ObjectNotFoundException, InsufficientPermissionsException {
447 throw new ObjectNotFoundException("No user specified");
449 throw new ObjectNotFoundException("No group specified");
451 // Do the actual work.
452 final User owner = dao.getEntityById(User.class, userId);
453 final Group group = dao.getEntityById(Group.class, groupId);
454 // Only delete the group if actually owned by the user.
455 if (group.getOwner().equals(owner)) {
456 List<Folder> folders = dao.getFoldersPermittedForGroup(userId, groupId);
457 for (Folder f : folders){
458 f.getPermissions().removeAll(group.getPermissions());
459 for(FileHeader file : f.getFiles())
460 file.getPermissions().removeAll(group.getPermissions());
462 List<FileHeader> files = dao.getSharedFilesNotInSharedFolders(userId);
463 for(FileHeader h : files)
464 h.getPermissions().removeAll(group.getPermissions());
465 owner.removeSpecifiedGroup(group);
468 else throw new InsufficientPermissionsException("You are not the owner of this group");
472 public FileHeaderDTO createFile(Long userId, Long folderId, String name, String mimeType, InputStream stream)
473 throws DuplicateNameException, ObjectNotFoundException, GSSIOException,
474 InsufficientPermissionsException, QuotaExceededException {
477 file = uploadFile(stream, userId);
478 } catch ( IOException ioe) {
479 // Supply a more accurate problem description.
480 throw new GSSIOException("Problem creating file",ioe);
482 return createFile(userId, folderId, name, mimeType, file);
486 * @see gr.ebs.gss.server.ejb.ExternalAPIRemote#indexFile(java.lang.Long, boolean)
488 public void indexFile(Long fileId, boolean delete) {
489 Connection qConn = null;
490 Session session = null;
491 MessageProducer sender = null;
493 Context jndiCtx = new InitialContext();
494 ConnectionFactory factory = (QueueConnectionFactory) jndiCtx.lookup("java:/JmsXA");
495 Queue queue = (Queue) jndiCtx.lookup("queue/gss-indexingQueue");
496 qConn = factory.createConnection();
497 session = qConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
498 sender = session.createProducer(queue);
500 MapMessage map = session.createMapMessage();
501 map.setObject("id", fileId);
502 map.setBoolean("delete", delete);
505 catch (NamingException e) {
506 logger.error("Index was not updated: ", e);
508 catch (JMSException e) {
509 logger.error("Index was not updated: ", e);
520 catch (JMSException e) {
529 * A helper method that generates a unique file path for a stored file. The
530 * files are stored using random hash names that are distributed evenly in
531 * a 2-level tree of subdirectories named after the first two hex characters
532 * in the name. For example, file ab1234cd5769f will be stored in the path
533 * /file-repository-root/a/b/ab1234cd5769f. The directories will be created
534 * if they don't already exist.
536 * @return a unique new file path
538 private String generateRepositoryFilePath() {
539 String filename = Long.toHexString(random.nextLong());
540 String fileRepositoryPath = getConfiguration().getString("fileRepositoryPath","/tmp");
541 File root = new File(fileRepositoryPath);
544 File firstFolder = new File(root + File.separator + filename.substring(0, 1));
545 if (!firstFolder.exists())
547 File secondFolder = new File(firstFolder + File.separator + filename.substring(1, 2));
548 if (!secondFolder.exists())
549 secondFolder.mkdir();
550 return secondFolder + File.separator + filename;
556 * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteFile(java.lang.Long,
559 public void deleteFile(final Long userId, final Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
562 throw new ObjectNotFoundException("No user specified");
564 throw new ObjectNotFoundException("No file specified");
566 // Do the actual work.
567 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
568 final Folder parent = file.getFolder();
570 throw new ObjectNotFoundException("The specified file has no parent folder");
571 final User user = dao.getEntityById(User.class, userId);
572 if (!file.hasDeletePermission(user))
573 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
574 for (final FileBody body : file.getBodies()) {
575 final File fileContents = new File(body.getStoredFilePath());
576 if (!fileContents.delete())
577 logger.error("Could not delete file " + body.getStoredFilePath());
580 indexFile(fileId, true);
586 * @see gr.ebs.gss.server.ejb.ExternalAPI#createTag(java.lang.Long,
587 * java.lang.Long, java.lang.String)
589 public void createTag(final Long userId, final Long fileHeaderId, final String tag) throws ObjectNotFoundException {
591 throw new ObjectNotFoundException("No user specified");
592 if (fileHeaderId == null)
593 throw new ObjectNotFoundException("No file specified");
594 if (StringUtils.isEmpty(tag))
595 throw new ObjectNotFoundException("Tag is empty");
597 final User user = dao.getEntityById(User.class, userId);
598 final FileHeader fh = dao.getEntityById(FileHeader.class, fileHeaderId);
599 user.addTag(fh, tag);
603 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUserTags(java.lang.Long)
605 @WebMethod(operationName = "getUserTags")
606 public Set<String> getUserTags(final Long userId) throws ObjectNotFoundException {
607 return dao.getUserTags(userId);
611 * @see gr.ebs.gss.server.ejb.ExternalAPI#updateFile(java.lang.Long, java.lang.Long, java.lang.String, java.util.Set)
613 public void updateFile(Long userId, Long fileId, String name, String tagSet) throws ObjectNotFoundException, InsufficientPermissionsException {
615 throw new ObjectNotFoundException("No user specified");
617 throw new ObjectNotFoundException("No file specified");
618 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
619 User user = dao.getEntityById(User.class, userId);
620 if (!file.hasWritePermission(user))
621 throw new InsufficientPermissionsException("User " + user.getId() + " cannot update file " + file.getName() + "(" + file.getId() + ")");
625 List<FileTag> tags = file.getFileTags();
627 if (tagSet != null) {
628 Iterator<FileTag> i = tags.iterator();
629 while (i.hasNext()) {
630 FileTag tag = i.next();
637 StringTokenizer st = new StringTokenizer(tagSet, ",");
638 while (st.hasMoreTokens())
639 new FileTag(user, file, st.nextToken().trim());
642 // Re-index the file if it was modified.
643 if (name != null || tagSet != null)
644 indexFile(fileId, false);
648 public InputStream getFileContents(Long userId, Long fileId)
649 throws ObjectNotFoundException, InsufficientPermissionsException {
651 throw new ObjectNotFoundException("No user specified");
653 throw new ObjectNotFoundException("No file specified");
655 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
656 User user = dao.getEntityById(User.class, userId);
657 if (!header.hasReadPermission(user)) {
658 logger.info("User " + user.getId() + " cannot read file " + header.getName() + "(" + fileId + ")");
659 throw new InsufficientPermissionsException("You don't have the necessary permissions");
662 File f = new File(header.getCurrentBody().getStoredFilePath());
664 return new FileInputStream(f);
665 } catch (FileNotFoundException e) {
666 logger.error("Could not locate the contents of file " + f.getAbsolutePath());
667 throw new ObjectNotFoundException("The file contents could not be located");
672 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFileContents(java.lang.Long, java.lang.Long, java.lang.Long)
674 public InputStream getFileContents(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
676 throw new ObjectNotFoundException("No user specified");
678 throw new ObjectNotFoundException("No file specified");
680 throw new ObjectNotFoundException("No file specified");
682 final FileHeader header = dao.getEntityById(FileHeader.class, fileId);
683 final FileBody body = dao.getEntityById(FileBody.class, bodyId);
684 final User user = dao.getEntityById(User.class, userId);
685 if (!header.hasReadPermission(user)) {
686 logger.info("User " + user.getId() + " cannot read file " + header.getName() + "(" + fileId + ")");
687 throw new InsufficientPermissionsException("You don't have the necessary permissions");
690 File f = new File(body.getStoredFilePath());
692 return new FileInputStream(f);
693 } catch (FileNotFoundException e) {
694 logger.error("Could not locate the contents of file " + f.getAbsolutePath());
695 throw new ObjectNotFoundException("The file contents could not be located");
700 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFile(java.lang.Long, java.lang.Long)
702 public FileHeaderDTO getFile(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
704 throw new ObjectNotFoundException("No user specified");
706 throw new ObjectNotFoundException("No file specified");
707 final User user = dao.getEntityById(User.class, userId);
708 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
709 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
710 throw new InsufficientPermissionsException("You don't have the necessary permissions");
711 return file.getDTO();
715 public FileBodyDTO getFileBody(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
717 throw new ObjectNotFoundException("No user specified");
719 throw new ObjectNotFoundException("No file specified");
720 User user = dao.getEntityById(User.class, userId);
721 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
722 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
723 throw new InsufficientPermissionsException("You don't have the necessary permissions");
724 FileBody body = dao.getEntityById(FileBody.class, bodyId);
725 return body.getDTO();
729 public Object getResourceAtPath(Long ownerId, String path, boolean ignoreDeleted)
730 throws ObjectNotFoundException {
732 throw new ObjectNotFoundException("No user specified");
733 if (StringUtils.isEmpty(path))
734 throw new ObjectNotFoundException("No path specified");
736 User owner = dao.getEntityById(User.class, ownerId);
737 List<String> pathElements = new ArrayList<String>();
738 StringTokenizer st = new StringTokenizer(path, "/");
739 while (st.hasMoreTokens())
740 pathElements.add(st.nextToken());
741 if (pathElements.size() < 1)
742 return getRootFolder(owner.getId());
743 // Store the last element, since it requires special handling.
744 String lastElement = pathElements.remove(pathElements.size() - 1);
745 FolderDTO cursor = getRootFolder(owner.getId());
746 // Traverse and verify the specified folder path.
747 for (String pathElement : pathElements) {
748 cursor = getFolder(cursor.getId(), pathElement);
749 if (cursor.isDeleted())
750 throw new ObjectNotFoundException("Folder " + cursor.getPath() + " not found");
753 // Use the lastElement to retrieve the actual resource.
754 Object resource = null;
756 FileHeaderDTO file = getFile(cursor.getId(), lastElement);
757 if (ignoreDeleted && file.isDeleted())
758 throw new ObjectNotFoundException("Resource not found");
760 } catch (ObjectNotFoundException e) {
761 // Perhaps the requested resource is not a file, so
762 // check for folders as well.
763 FolderDTO folder = getFolder(cursor.getId(), lastElement);
764 if (ignoreDeleted && folder.isDeleted())
765 throw new ObjectNotFoundException("Resource not found");
772 * Retrieve a file for the specified user that has the specified name and
773 * its parent folder has id equal to folderId.
775 * @param userId the ID of the current user
776 * @param folderId the ID of the parent folder
777 * @param name the name of the requested file
778 * @return the file found
779 * @throws ObjectNotFoundException if the specified folder or file was not
780 * found, with the exception message mentioning the precise
783 private FileHeaderDTO getFile(Long folderId, String name) throws ObjectNotFoundException {
784 if (folderId == null)
785 throw new ObjectNotFoundException("No parent folder specified");
786 if (StringUtils.isEmpty(name))
787 throw new ObjectNotFoundException("No file specified");
789 FileHeader file = dao.getFile(folderId, name);
790 return file.getDTO();
794 * Retrieve a folder for the specified user that has the specified name and
795 * its parent folder has id equal to parentId.
797 * @param parentId the ID of the parent folder
798 * @param name the name of the requested folder
799 * @return the folder found
800 * @throws ObjectNotFoundException if the specified folder or parent was not
801 * found, with the exception message mentioning the precise
804 private FolderDTO getFolder(Long parentId, String name) throws ObjectNotFoundException {
805 if (parentId == null)
806 throw new ObjectNotFoundException("No parent folder specified");
807 if (StringUtils.isEmpty(name))
808 throw new ObjectNotFoundException("No folder specified");
810 Folder folder = dao.getFolder(parentId, name);
811 return folder.getDTO();
814 private FileHeaderDTO updateFileContents(Long userId, Long fileId, String mimeType, InputStream resourceInputStream) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
817 file = uploadFile(resourceInputStream, userId);
818 } catch ( IOException ioe) {
819 // Supply a more accurate problem description.
820 throw new GSSIOException("Problem creating file",ioe);
822 return updateFileContents(userId, fileId, mimeType, file);
826 public void copyFile(Long userId, Long fileId, String dest) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
828 throw new ObjectNotFoundException("No user specified");
830 throw new ObjectNotFoundException("No file specified");
831 if (StringUtils.isEmpty(dest))
832 throw new ObjectNotFoundException("No destination specified");
834 Object destination = getResourceAtPath(userId, getParentPath(dest), true);
835 if (!(destination instanceof FolderDTO))
836 throw new ObjectNotFoundException("Destination parent folder not found");
837 FolderDTO parent = (FolderDTO) destination;
838 copyFile(userId, fileId, parent.getId(), getLastElement(dest));
842 public void copyFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
844 throw new ObjectNotFoundException("No user specified");
846 throw new ObjectNotFoundException("No owner specified");
848 throw new ObjectNotFoundException("No file specified");
849 if (StringUtils.isEmpty(dest))
850 throw new ObjectNotFoundException("No destination specified");
852 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
853 if (!(destination instanceof FolderDTO))
854 throw new ObjectNotFoundException("Destination parent folder not found");
855 FolderDTO parent = (FolderDTO) destination;
856 copyFile(userId, fileId, parent.getId(), getLastElement(dest));
860 public void copyFile(Long userId, Long fileId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
862 throw new ObjectNotFoundException("No user specified");
864 throw new ObjectNotFoundException("No file specified");
866 throw new ObjectNotFoundException("No destination specified");
867 if (StringUtils.isEmpty(destName))
868 throw new ObjectNotFoundException("No destination file name specified");
870 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
871 Folder destination = dao.getEntityById(Folder.class, destId);
872 User user = dao.getEntityById(User.class, userId);
873 if (!file.hasReadPermission(user) || !destination.hasWritePermission(user))
874 throw new InsufficientPermissionsException("You don't have the necessary permissions");
875 int versionsNumber = file.getBodies().size();
876 FileBody oldestBody = file.getBodies().get(0);
877 assert oldestBody != null;
878 File contents = new File(oldestBody.getStoredFilePath());
880 createFile(user.getId(), destination.getId(), destName, oldestBody.getMimeType(), new FileInputStream(contents));
881 FileHeader copiedFile = dao.getFile(destination.getId(), destName);
883 if (versionsNumber > 1)
884 for (int i = 1; i < versionsNumber; i++) {
885 FileBody body = file.getBodies().get(i);
887 contents = new File(body.getStoredFilePath());
888 updateFileContents(user.getId(), copiedFile.getId(), body.getMimeType(), new FileInputStream(contents));
890 List<FileTag> tags = file.getFileTags();
891 for (FileTag tag : tags)
892 createTag(userId, copiedFile.getId(), tag.getTag());
894 } catch (FileNotFoundException e) {
895 throw new ObjectNotFoundException("File contents not found for file " + contents.getAbsolutePath());
901 public void copyFolder(Long userId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
903 throw new ObjectNotFoundException("No user specified");
904 if (folderId == null)
905 throw new ObjectNotFoundException("No folder specified");
906 if (StringUtils.isEmpty(dest))
907 throw new ObjectNotFoundException("No destination specified");
909 Object destination = getResourceAtPath(userId, getParentPath(dest), true);
910 if (!(destination instanceof FolderDTO))
911 throw new ObjectNotFoundException("Destination folder not found");
912 FolderDTO parent = (FolderDTO) destination;
913 copyFolder(userId, folderId, parent.getId(), getLastElement(dest));
917 public void copyFolder(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
919 throw new ObjectNotFoundException("No user specified");
920 if (folderId == null)
921 throw new ObjectNotFoundException("No folder specified");
923 throw new ObjectNotFoundException("No destination specified");
924 if (StringUtils.isEmpty(destName))
925 throw new ObjectNotFoundException("No destination folder name specified");
926 Folder folder = dao.getEntityById(Folder.class, folderId);
927 Folder destination = dao.getEntityById(Folder.class, destId);
928 User user = dao.getEntityById(User.class, userId);
929 if (!destination.hasWritePermission(user) || !folder.hasReadPermission(user))
930 throw new InsufficientPermissionsException("You don't have the necessary permissions");
931 createFolder(user.getId(), destination.getId(), destName);
935 public void copyFolderStructureToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
937 throw new ObjectNotFoundException("No user specified");
939 throw new ObjectNotFoundException("No owner specified");
940 if (folderId == null)
941 throw new ObjectNotFoundException("No folder specified");
942 if (StringUtils.isEmpty(dest))
943 throw new ObjectNotFoundException("No destination specified");
945 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
946 if (!(destination instanceof FolderDTO))
947 throw new ObjectNotFoundException("Destination folder not found");
948 FolderDTO parent = (FolderDTO) destination;
949 copyFolderStructure(userId, folderId, parent.getId(), getLastElement(dest));
953 public void copyFolderStructure(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
955 throw new ObjectNotFoundException("No user specified");
956 if (folderId == null)
957 throw new ObjectNotFoundException("No folder specified");
959 throw new ObjectNotFoundException("No destination specified");
960 if (StringUtils.isEmpty(destName))
961 throw new ObjectNotFoundException("No destination folder name specified");
963 Folder folder = dao.getEntityById(Folder.class, folderId);
964 Folder destination = dao.getEntityById(Folder.class, destId);
965 final User user = dao.getEntityById(User.class, userId);
966 // XXX: quick fix need to copy only visible items to user (Source
968 if (!folder.getOwner().getId().equals(userId) && !folder.hasReadPermission(user))
970 if(folder.isDeleted())//do not copy trashed folder and contents
972 if (!destination.hasWritePermission(user) || !folder.hasReadPermission(user))
973 throw new InsufficientPermissionsException("You don't have the necessary permissions");
974 createFolder(user.getId(), destination.getId(), destName);
975 Folder createdFolder = dao.getFolder(destination.getId(), destName);
976 List<FileHeader> files = folder.getFiles();
978 for (FileHeader file : files)
979 if(!file.isDeleted())
980 copyFile(userId, file.getId(), createdFolder.getId(), file.getName());
981 List<Folder> subFolders = folder.getSubfolders();
982 if (subFolders != null)
983 for (Folder sub : subFolders)
984 if(!sub.getId().equals(createdFolder.getId()))
985 copyFolderStructure(userId, sub.getId(), createdFolder.getId(), sub.getName());
990 * For a provided path, remove the last element and return the rest, that is
991 * the path of the parent folder.
993 * @param path the specified path
994 * @return the path of the parent folder
995 * @throws ObjectNotFoundException if the provided string contains no path
998 private String getParentPath(String path) throws ObjectNotFoundException {
999 int lastDelimiter = path.lastIndexOf('/');
1000 if (lastDelimiter == 0)
1002 if (lastDelimiter == -1)
1004 throw new ObjectNotFoundException("There is no parent in the path: " + path);
1005 else if (lastDelimiter < path.length() - 1)
1006 // Return the part before the delimiter.
1007 return path.substring(0, lastDelimiter);
1009 // Remove the trailing delimiter and then recurse.
1010 String strippedTrail = path.substring(0, lastDelimiter);
1011 return getParentPath(strippedTrail);
1016 * Get the last element in a path that denotes the file or folder name.
1018 * @param path the provided path
1019 * @return the last element in the path
1021 private String getLastElement(String path) {
1022 int lastDelimiter = path.lastIndexOf('/');
1023 if (lastDelimiter == -1)
1026 else if (lastDelimiter < path.length() - 1)
1027 // Return the part after the delimiter.
1028 return path.substring(lastDelimiter + 1);
1030 // Remove the trailing delimiter and then recurse.
1031 String strippedTrail = path.substring(0, lastDelimiter);
1032 return getLastElement(strippedTrail);
1037 public void moveFileToTrash(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1039 throw new ObjectNotFoundException("No user specified");
1041 throw new ObjectNotFoundException("No file specified");
1043 // Do the actual work.
1044 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1045 Folder parent = file.getFolder();
1047 throw new ObjectNotFoundException("The specified file has no parent folder");
1048 User user = dao.getEntityById(User.class, userId);
1049 if (!file.hasDeletePermission(user))
1050 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
1052 file.setDeleted(true);
1057 public void moveFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, InsufficientPermissionsException, DuplicateNameException, GSSIOException, QuotaExceededException {
1059 throw new ObjectNotFoundException("No user specified");
1060 if (ownerId == null)
1061 throw new ObjectNotFoundException("No owner specified");
1063 throw new ObjectNotFoundException("No file specified");
1064 if (StringUtils.isEmpty(dest))
1065 throw new ObjectNotFoundException("No destination specified");
1067 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1068 if (!(destination instanceof FolderDTO))
1069 throw new ObjectNotFoundException("Destination parent folder not found");
1070 FolderDTO parent = (FolderDTO) destination;
1071 moveFile(userId, fileId, parent.getId(), getLastElement(dest));
1075 public void moveFile(Long userId, Long fileId, Long destId, String destName) throws InsufficientPermissionsException, ObjectNotFoundException, DuplicateNameException, GSSIOException, QuotaExceededException {
1077 throw new ObjectNotFoundException("No user specified");
1079 throw new ObjectNotFoundException("No file specified");
1081 throw new ObjectNotFoundException("No destination specified");
1082 if (StringUtils.isEmpty(destName))
1083 throw new ObjectNotFoundException("No destination file name specified");
1085 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1086 Folder destination = dao.getEntityById(Folder.class, destId);
1088 User owner = dao.getEntityById(User.class, userId);
1089 if (!file.hasDeletePermission(owner) || !destination.hasWritePermission(owner))
1090 throw new InsufficientPermissionsException("User " + owner.getId() + " cannot move file " + file.getName() + "(" + file.getId() + ")");
1091 FileBody body = file.getCurrentBody();
1092 assert body != null;
1093 File contents = new File(body.getStoredFilePath());
1095 createFile(owner.getId(), destination.getId(), destName, body.getMimeType(), new FileInputStream(contents));
1096 } catch (FileNotFoundException e) {
1097 throw new ObjectNotFoundException("File contents not found for file " + body.getStoredFilePath());
1099 deleteFile(userId, fileId);
1104 public void moveFolderToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1106 throw new ObjectNotFoundException("No user specified");
1107 if (ownerId == null)
1108 throw new ObjectNotFoundException("No owner specified");
1109 if (folderId == null)
1110 throw new ObjectNotFoundException("No folder specified");
1111 if (StringUtils.isEmpty(dest))
1112 throw new ObjectNotFoundException("No destination specified");
1114 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1115 if (!(destination instanceof FolderDTO))
1116 throw new ObjectNotFoundException("Destination parent folder not found");
1117 FolderDTO parent = (FolderDTO) destination;
1118 moveFolder(userId, folderId, parent.getId(), getLastElement(dest));
1122 public void moveFolder(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1123 // TODO Simple Move and delete of original folder, in production
1124 // scenario we must first check individual files and folders permissions
1125 copyFolderStructure(userId, folderId, destId, destName);
1126 deleteFolder(userId, folderId);
1130 * @see gr.ebs.gss.server.ejb.ExternalAPI#getDeletedFiles(java.lang.Long)
1132 public List<FileHeaderDTO> getDeletedFiles(Long userId) throws ObjectNotFoundException {
1135 throw new ObjectNotFoundException("No user specified");
1137 // Do the actual work.
1138 final List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1139 final List<FileHeader> files = dao.getDeletedFiles(userId);
1140 for (final FileHeader f : files)
1141 result.add(f.getDTO());
1146 public void removeFileFromTrash(Long userId, Long fileId)
1147 throws ObjectNotFoundException, InsufficientPermissionsException {
1149 throw new ObjectNotFoundException("No user specified");
1151 throw new ObjectNotFoundException("No file specified");
1153 // Do the actual work.
1154 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1155 Folder parent = file.getFolder();
1157 throw new ObjectNotFoundException("The specified file has no parent folder");
1158 User user = dao.getEntityById(User.class, userId);
1159 if (!file.hasDeletePermission(user))
1160 throw new InsufficientPermissionsException("User " + user.getUsername() +
1161 " cannot restore file " + file.getName());
1163 file.setDeleted(false);
1168 public void moveFolderToTrash(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
1170 throw new ObjectNotFoundException("No user specified");
1171 if (folderId == null)
1172 throw new ObjectNotFoundException("No folder specified");
1173 Folder folder = dao.getEntityById(Folder.class, folderId);
1174 User user = dao.getEntityById(User.class, userId);
1175 if (!folder.hasDeletePermission(user))
1176 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1177 folder.setDeleted(true);
1179 for (FileHeader file : folder.getFiles())
1180 moveFileToTrash(userId, file.getId());
1181 for (Folder subFolder : folder.getSubfolders())
1182 moveFolderToTrash(userId, subFolder.getId());
1187 public void removeFolderFromTrash(Long userId, Long folderId)
1188 throws ObjectNotFoundException, InsufficientPermissionsException {
1190 throw new ObjectNotFoundException("No user specified");
1191 if (folderId == null)
1192 throw new ObjectNotFoundException("No folder specified");
1193 Folder folder = dao.getEntityById(Folder.class, folderId);
1194 User user = dao.getEntityById(User.class, userId);
1195 if (!folder.hasDeletePermission(user))
1196 throw new InsufficientPermissionsException("User " + user.getUsername() +
1197 " cannot restore folder " + folder.getName());
1198 folder.setDeleted(false);
1199 for (FileHeader file : folder.getFiles())
1200 removeFileFromTrash(userId, file.getId());
1201 for (Folder subFolder : folder.getSubfolders())
1202 removeFolderFromTrash(userId, subFolder.getId());
1207 public List<FolderDTO> getDeletedRootFolders(Long userId) throws ObjectNotFoundException {
1208 List<Folder> folders = dao.getDeletedRootFolders(userId);
1209 List<FolderDTO> result = new ArrayList<FolderDTO>();
1210 for (Folder folder : folders)
1211 result.add(folder.getDTO());
1216 public void emptyTrash(Long userId) throws ObjectNotFoundException, InsufficientPermissionsException {
1217 List<FolderDTO> deletedRootFolders = getDeletedRootFolders(userId);
1218 for (FolderDTO fdto : deletedRootFolders)
1219 deleteFolder(userId, fdto.getId());
1220 List<FileHeaderDTO> deletedFiles = getDeletedFiles(userId);
1221 for (FileHeaderDTO filedto : deletedFiles)
1222 deleteFile(userId, filedto.getId());
1226 public void restoreTrash(Long userId) throws ObjectNotFoundException, InsufficientPermissionsException {
1227 List<FolderDTO> deletedRootFolders = getDeletedRootFolders(userId);
1228 for (FolderDTO fdto : deletedRootFolders)
1229 removeFolderFromTrash(userId, fdto.getId());
1230 List<FileHeaderDTO> deletedFiles = getDeletedFiles(userId);
1231 for (FileHeaderDTO filedto : deletedFiles)
1232 removeFileFromTrash(userId, filedto.getId());
1236 public User createUser(String username, String name, String mail) throws ObjectNotFoundException {
1237 if (username == null)
1238 throw new ObjectNotFoundException("No username specified");
1240 throw new ObjectNotFoundException("No name specified");
1242 User user = new User();
1243 user.setUsername(username);
1245 user.setEmail(mail);
1246 Date now = new Date();
1247 AuditInfo auditInfo = new AuditInfo();
1248 auditInfo.setCreationDate(now);
1249 auditInfo.setModificationDate(now);
1250 user.setAuditInfo(auditInfo);
1251 user.generateAuthToken();
1253 // Make sure we get an ID in the user object.
1255 // Create the root folder for the user.
1256 createFolder(user.getName(), null, user);
1261 public User findUserByEmail(String email) {
1262 return dao.findUserByEmail(email);
1266 public void updateUser(User user) {
1271 public User updateUser(String username, String name, String mail) throws ObjectNotFoundException {
1272 if (username == null)
1273 throw new ObjectNotFoundException("No username specified");
1275 User user = dao.getUser(username);
1277 user.setEmail(mail);
1282 public User findUser(String username) {
1283 if (username == null)
1285 return dao.findUser(username);
1289 public User updateUserToken(Long userId) throws ObjectNotFoundException {
1291 throw new ObjectNotFoundException("No user specified");
1292 User user = dao.getEntityById(User.class, userId);
1293 user.generateAuthToken();
1298 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFolderPermissions(java.lang.Long, java.lang.Long)
1301 public Set<PermissionDTO> getFolderPermissions(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
1303 throw new ObjectNotFoundException("No user specified");
1304 if (folderId == null)
1305 throw new ObjectNotFoundException("No folder specified");
1306 User user = dao.getEntityById(User.class, userId);
1307 Folder folder = dao.getEntityById(Folder.class, folderId);
1308 if(!folder.hasReadPermission(user))
1309 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1310 Set<Permission> perms = folder.getPermissions();
1311 Set<PermissionDTO> result = new LinkedHashSet<PermissionDTO>();
1312 for (Permission perm : perms)
1313 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId()))
1314 result.add(perm.getDTO());
1315 for (Permission perm : perms)
1316 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId())) {
1318 result.add(perm.getDTO());
1324 * @see gr.ebs.gss.server.ejb.ExternalAPI#setFolderPermissions(java.lang.Long, java.lang.Long, java.util.Set)
1327 public void setFolderPermissions(Long userId, Long folderId, Set<PermissionDTO> permissions) throws ObjectNotFoundException, InsufficientPermissionsException {
1329 throw new ObjectNotFoundException("No user specified");
1330 if (folderId == null)
1331 throw new ObjectNotFoundException("No folder specified");
1332 User user = dao.getEntityById(User.class, userId);
1333 Folder folder = dao.getEntityById(Folder.class, folderId);
1334 if(!folder.hasModifyACLPermission(user))
1335 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1336 folder.getPermissions().clear();
1337 for (PermissionDTO dto : permissions) {
1338 if (dto.getUser()!=null && dto.getUser().getId().equals(folder.getOwner().getId()) && (!dto.hasRead() || !dto.hasWrite() || !dto.hasModifyACL()))
1339 throw new InsufficientPermissionsException("Can't remove permissions from owner");
1340 folder.addPermission(getPermission(dto));
1343 for (FileHeader fh : folder.getFiles())
1344 setFilePermissions(userId, fh.getId(), fh.isReadForAll(), permissions);
1345 for (Folder sub : folder.getSubfolders())
1346 setFolderPermissions(userId, sub.getId(), permissions);
1349 private Permission getPermission(PermissionDTO dto) throws ObjectNotFoundException {
1350 Permission res = new Permission();
1351 if (dto.getGroup() != null)
1352 res.setGroup(dao.getEntityById(Group.class, dto.getGroup().getId()));
1353 else if (dto.getUser() != null)
1354 if (dto.getUser().getId() == null)
1355 res.setUser(dao.getUser(dto.getUser().getUsername()));
1357 res.setUser(dao.getEntityById(User.class, dto.getUser().getId()));
1358 res.setRead(dto.hasRead());
1359 res.setWrite(dto.hasWrite());
1360 res.setModifyACL(dto.hasModifyACL());
1365 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsersByUserNameLike(java.lang.String)
1368 public List<UserDTO> getUsersByUserNameLike(String username) {
1369 List<User> users = dao.getUsersByUserNameLike(username);
1370 List<UserDTO> result = new ArrayList<UserDTO>();
1371 for (User u : users)
1372 result.add(u.getDTO());
1378 * @see gr.ebs.gss.server.ejb.ExternalAPI#addUserToGroup(java.lang.Long, java.lang.Long, java.lang.Long)
1381 public void addUserToGroup(Long userId, Long groupId, Long userToAddId) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
1383 throw new ObjectNotFoundException("No user specified");
1384 if (groupId == null)
1385 throw new ObjectNotFoundException("No group specified");
1386 if (userToAddId == null)
1387 throw new ObjectNotFoundException("No user to add specified");
1388 User user = dao.getEntityById(User.class, userId);
1389 Group group = dao.getEntityById(Group.class, groupId);
1390 if (!group.getOwner().equals(user))
1391 throw new InsufficientPermissionsException();
1392 User userToAdd = dao.getEntityById(User.class, userToAddId);
1393 if (group.contains(userToAdd))
1394 throw new DuplicateNameException("User already exists in group");
1395 group.getMembers().add(userToAdd);
1401 public void invalidateUserToken(Long userId) throws ObjectNotFoundException {
1403 throw new ObjectNotFoundException("No user specified");
1404 User user = dao.getEntityById(User.class, userId);
1405 user.invalidateAuthToken();
1410 public List<FolderDTO> getSharedRootFolders(Long userId) throws ObjectNotFoundException {
1412 throw new ObjectNotFoundException("No user specified");
1413 List<Folder> folders = dao.getSharedRootFolders(userId);
1414 List<FolderDTO> result = new ArrayList<FolderDTO>();
1415 for (Folder f : folders) {
1416 FolderDTO dto = f.getDTO();
1417 dto.setSubfolders(getSharedSubfolders(userId, f.getId()));
1424 * @see gr.ebs.gss.server.ejb.ExternalAPI#removeMemberFromGroup(java.lang.Long, java.lang.Long, java.lang.Long)
1427 public void removeMemberFromGroup(Long userId, Long groupId, Long memberId) throws ObjectNotFoundException, InsufficientPermissionsException {
1429 throw new ObjectNotFoundException("No user specified");
1430 if (groupId == null)
1431 throw new ObjectNotFoundException("No group specified");
1432 if (memberId == null)
1433 throw new ObjectNotFoundException("No member specified");
1434 User owner = dao.getEntityById(User.class, userId);
1435 Group group = dao.getEntityById(Group.class, groupId);
1436 User member = dao.getEntityById(User.class, memberId);
1437 if (!group.getOwner().equals(owner))
1438 throw new InsufficientPermissionsException("User is not the owner of the group");
1439 group.removeMemberFromGroup(member);
1445 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsersSharingFoldersForUser(java.lang.Long)
1448 public List<UserDTO> getUsersSharingFoldersForUser(Long userId) throws ObjectNotFoundException {
1449 List<User> users = dao.getUsersSharingFoldersForUser(userId);
1450 List<User> usersFiles = dao.getUsersSharingFilesForUser(userId);
1451 List<UserDTO> res = new ArrayList<UserDTO>();
1452 for (User u : users)
1453 res.add(u.getDTO());
1454 for(User fu : usersFiles)
1455 if(!users.contains(fu))
1456 res.add(fu.getDTO());
1461 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFilePermissions(java.lang.Long, java.lang.Long)
1464 public Set<PermissionDTO> getFilePermissions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1466 throw new ObjectNotFoundException("No user specified");
1468 throw new ObjectNotFoundException("No folder specified");
1469 User user = dao.getEntityById(User.class, userId);
1470 FileHeader folder = dao.getEntityById(FileHeader.class, fileId);
1471 if(!folder.hasReadPermission(user))
1472 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1473 Set<Permission> perms = folder.getPermissions();
1474 Set<PermissionDTO> result = new LinkedHashSet<PermissionDTO>();
1475 for (Permission perm : perms)
1476 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId()))
1477 result.add(perm.getDTO());
1478 for (Permission perm : perms)
1479 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId())) {
1481 result.add(perm.getDTO());
1486 public void setFilePermissions(Long userId, Long fileId, Boolean readForAll, Set<PermissionDTO> permissions) throws ObjectNotFoundException, InsufficientPermissionsException {
1488 throw new ObjectNotFoundException("No user specified");
1490 throw new ObjectNotFoundException("No folder specified");
1492 User user = dao.getEntityById(User.class, userId);
1493 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1494 if(!file.hasModifyACLPermission(user))
1495 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1497 if (readForAll != null)
1498 if (user.equals(file.getOwner()))
1499 file.setReadForAll(readForAll);
1501 throw new InsufficientPermissionsException("Only the owner can change the read-for-all flag");
1503 if (permissions != null && !permissions.isEmpty()) {
1504 file.getPermissions().clear();
1505 for (PermissionDTO dto : permissions) {
1506 if (dto.getUser()!=null && dto.getUser().getId().equals(file.getOwner().getId()) && (!dto.hasRead() || !dto.hasWrite() || !dto.hasModifyACL()))
1507 throw new InsufficientPermissionsException("Can't remove permissions from owner");
1508 file.addPermission(getPermission(dto));
1512 // Update the file if there was a change.
1513 if (readForAll != null || permissions != null && !permissions.isEmpty())
1519 public List<FileHeaderDTO> getSharedFilesNotInSharedFolders(Long userId) throws ObjectNotFoundException {
1521 throw new ObjectNotFoundException("No user specified");
1522 List<FileHeader> files = dao.getSharedFilesNotInSharedFolders(userId);
1523 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1524 for (FileHeader f : files)
1525 result.add(f.getDTO());
1530 public List<FileHeaderDTO> getSharedFiles(Long userId) throws ObjectNotFoundException {
1532 throw new ObjectNotFoundException("No user specified");
1533 List<FileHeader> files = dao.getSharedFiles(userId);
1534 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1535 for (FileHeader f : files)
1536 result.add(f.getDTO());
1541 public List<FolderDTO> getSharedFolders(Long userId) throws ObjectNotFoundException {
1543 throw new ObjectNotFoundException("No user specified");
1544 List<Folder> folders = dao.getSharedFolders(userId);
1545 List<FolderDTO> result = new ArrayList<FolderDTO>();
1546 for (Folder f : folders)
1547 result.add(f.getDTO());
1552 * @see gr.ebs.gss.server.ejb.ExternalAPI#getSharedFiles(java.lang.Long, java.lang.Long)
1555 public List<FileHeaderDTO> getSharedFiles(Long ownerId, Long callingUserId) throws ObjectNotFoundException {
1556 if (ownerId == null)
1557 throw new ObjectNotFoundException("No owner specified");
1558 if (callingUserId == null)
1559 throw new ObjectNotFoundException("No calling user specified");
1560 List<FileHeader> folders = dao.getSharedFiles(ownerId, callingUserId);
1561 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1562 for (FileHeader f : folders)
1563 result.add(f.getDTO());
1568 public List<FolderDTO> getSharedRootFolders(Long ownerId, Long callingUserId) throws ObjectNotFoundException {
1569 if (ownerId == null)
1570 throw new ObjectNotFoundException("No owner specified");
1571 if (callingUserId == null)
1572 throw new ObjectNotFoundException("No calling user specified");
1573 List<Folder> folders = dao.getSharedRootFolders(ownerId, callingUserId);
1574 List<FolderDTO> result = new ArrayList<FolderDTO>();
1575 for (Folder f : folders) {
1576 FolderDTO dto = f.getDTO();
1577 dto.setSubfolders(getSharedSubfolders(ownerId, callingUserId, f.getId()));
1585 public List<FolderDTO> getSharedSubfolders(Long userId, Long folderId) throws ObjectNotFoundException {
1587 throw new ObjectNotFoundException("No user specified");
1588 if (folderId == null)
1589 throw new ObjectNotFoundException("No folder specified");
1590 User user = dao.getEntityById(User.class, userId);
1591 Folder folder = dao.getEntityById(Folder.class, folderId);
1592 List<FolderDTO> result = new ArrayList<FolderDTO>();
1593 if (folder.isShared(user))
1594 for (Folder f : folder.getSubfolders())
1595 if (f.isShared(user) && !f.isDeleted())
1596 result.add(f.getDTO());
1601 public List<FolderDTO> getSharedSubfolders(Long userId, Long callingUserId, Long folderId) throws ObjectNotFoundException {
1603 throw new ObjectNotFoundException("No user specified");
1604 if (callingUserId == null)
1605 throw new ObjectNotFoundException("No user specified");
1606 if (folderId == null)
1607 throw new ObjectNotFoundException("No folder specified");
1608 User user = dao.getEntityById(User.class, callingUserId);
1609 Folder folder = dao.getEntityById(Folder.class, folderId);
1610 List<FolderDTO> result = new ArrayList<FolderDTO>();
1611 if (folder.isSharedForOtherUser(user))
1612 for (Folder f : folder.getSubfolders())
1613 if (f.isSharedForOtherUser(user) && !f.isDeleted()){
1614 FolderDTO dto = f.getDTO();
1615 dto.setSubfolders(getSharedSubfolders(userId, callingUserId, dto.getId()));
1623 * @see gr.ebs.gss.server.ejb.ExternalAPI#searchFiles(java.lang.Long, java.lang.String)
1626 public List<FileHeaderDTO> searchFiles(Long userId, String query) throws ObjectNotFoundException {
1628 throw new ObjectNotFoundException("No user specified");
1629 User user = getUser(userId);
1631 throw new ObjectNotFoundException("No query specified");
1632 List<FileHeader> files = search(user.getId(), query);
1633 List<FileHeaderDTO> res = new ArrayList<FileHeaderDTO>();
1634 for(FileHeader f : files)
1635 res.add(f.getDTO());
1640 * Performs the actuals search on the solr server and returns the results
1642 * We have to use the dismax query type (instead of the
1643 * standard) because it allows for search time field boosting. This is because we can't use indexing
1644 * time field boosting due to the patched rich indexing API that does not allow it
1648 * @return a List of FileHeader objects
1650 private List<FileHeader> search(Long userId, String query) {
1652 HttpClient httpClient = new HttpClient();
1654 GetMethod method = new GetMethod(getConfiguration().getString("solrSelectUrl"));
1655 NameValuePair[] params = {new NameValuePair("qt", "dismax"),
1656 new NameValuePair("q", query),
1657 new NameValuePair("sort", "score desc"),
1658 new NameValuePair("indent", "on")};
1659 method.setQueryString(params);
1662 String response = null;
1664 statusCode = httpClient.executeMethod(method);
1665 logger.debug("HTTP status: " + statusCode);
1666 response = method.getResponseBodyAsString();
1667 logger.debug(response);
1669 if (statusCode != 200 && retryCount < 3)
1671 Thread.sleep(3000); //Give Solr a little time to be available
1672 } catch (InterruptedException e) {
1674 } while (statusCode != 200 && retryCount < 3);
1675 if (statusCode != 200)
1676 throw new EJBException("Search query return error:\n" + response);
1678 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
1679 DocumentBuilder db = dbf.newDocumentBuilder();
1680 Document doc = db.parse(method.getResponseBodyAsStream());
1681 method.releaseConnection();
1683 Node root = doc.getElementsByTagName("response").item(0);
1684 Node lst = root.getFirstChild().getNextSibling();
1685 Node status = lst.getFirstChild().getNextSibling();
1686 if (status.getAttributes().getNamedItem("name").getNodeValue().equals("status") &&
1687 status.getTextContent().equals("0")) {
1688 List<FileHeader> fileResult = new ArrayList<FileHeader>();
1689 Node result = lst.getNextSibling().getNextSibling();
1690 NodeList docs = result.getChildNodes();
1691 User user = getUser(userId);
1692 for (int i=1; i<docs.getLength(); i=i+2) {
1693 Node d = docs.item(i);
1694 NodeList docData = d.getChildNodes();
1695 for (int j=1; j<docData.getLength(); j=j+2) {
1696 Node dd = docData.item(j);
1697 if (dd.getAttributes().item(0).getNodeName().equals("name") &&
1698 dd.getAttributes().item(0).getNodeValue().equals("id")) {
1699 Long fileId = Long.valueOf(dd.getTextContent());
1701 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1702 if (file.hasReadPermission(user)) {
1703 fileResult.add(file);
1704 logger.debug("File added " + fileId);
1706 } catch (ObjectNotFoundException e) {
1707 logger.warn("Search result not found", e);
1714 throw new EJBException();
1715 } catch (HttpException e) {
1716 throw new EJBException(e);
1717 } catch (IOException e) {
1718 throw new EJBException(e);
1719 } catch (SAXException e) {
1720 throw new EJBException(e);
1721 } catch (ParserConfigurationException e) {
1722 throw new EJBException(e);
1723 } catch (ObjectNotFoundException e) {
1724 throw new EJBException(e);
1729 * @see gr.ebs.gss.server.ejb.ExternalAPI#copyFiles(java.lang.Long, java.util.List, java.lang.Long)
1732 public void copyFiles(Long userId, List<Long> fileIds, Long destId) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
1733 for(Long l : fileIds){
1734 FileHeader file = dao.getEntityById(FileHeader.class, l);
1735 copyFile(userId, l, destId, file.getName());
1742 * @see gr.ebs.gss.server.ejb.ExternalAPI#moveFiles(java.lang.Long, java.util.List, java.lang.Long)
1745 public void moveFiles(Long userId, List<Long> fileIds, Long destId) throws InsufficientPermissionsException, ObjectNotFoundException, DuplicateNameException, GSSIOException, QuotaExceededException {
1746 for(Long l : fileIds){
1747 FileHeader file = dao.getEntityById(FileHeader.class, l);
1748 moveFile(userId, l, destId, file.getName());
1754 * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteFiles(java.lang.Long, java.util.List)
1757 public void deleteFiles(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1759 throw new ObjectNotFoundException("No user specified");
1760 final User user = dao.getEntityById(User.class, userId);
1761 List<File> filesToRemove = new ArrayList<File>();
1762 //first delete database objects
1763 for(Long fileId : fileIds){
1765 throw new ObjectNotFoundException("No file specified");
1766 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1767 final Folder parent = file.getFolder();
1769 throw new ObjectNotFoundException("The specified file has no parent folder");
1770 if (!file.hasDeletePermission(user))
1771 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
1773 parent.removeFile(file);
1774 for (final FileBody body : file.getBodies()) {
1775 final File fileContents = new File(body.getStoredFilePath());
1776 filesToRemove.add(fileContents);
1780 //then remove physical files if everything is ok
1781 for(File physicalFile : filesToRemove)
1782 if (!physicalFile.delete())
1783 logger.error("Could not delete file " + physicalFile.getPath());
1784 //then unindex deleted files
1785 for(Long fileId : fileIds)
1786 indexFile(fileId, true);
1791 * @see gr.ebs.gss.server.ejb.ExternalAPI#moveFilesToTrash(java.lang.Long, java.util.List)
1794 public void moveFilesToTrash(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1795 for(Long l : fileIds)
1796 moveFileToTrash(userId, l);
1801 public void removeFilesFromTrash(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1802 for(Long l : fileIds)
1803 removeFileFromTrash(userId, l);
1808 public Nonce createNonce(Long userId) throws ObjectNotFoundException {
1810 throw new ObjectNotFoundException("No user specified");
1811 User user = dao.getEntityById(User.class, userId);
1812 Nonce nonce = Nonce.createNonce(user.getId());
1818 public Nonce getNonce(String nonce, Long userId) throws ObjectNotFoundException {
1820 throw new ObjectNotFoundException("No user specified");
1822 throw new ObjectNotFoundException("No nonce specified");
1823 return dao.getNonce(nonce, userId);
1827 public void removeNonce(Long id) throws ObjectNotFoundException {
1829 throw new ObjectNotFoundException("No nonce specified");
1830 Nonce nonce = dao.getEntityById(Nonce.class, id);
1835 public void activateUserNonce(Long userId, String nonce, Date nonceExpiryDate) throws ObjectNotFoundException {
1837 throw new ObjectNotFoundException("No user specified");
1838 User user = dao.getEntityById(User.class, userId);
1839 user.setNonce(nonce);
1840 user.setNonceExpiryDate(nonceExpiryDate);
1844 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUserStatistics(java.lang.Long)
1847 public StatsDTO getUserStatistics(Long userId) throws ObjectNotFoundException {
1849 throw new ObjectNotFoundException("No user specified");
1850 StatsDTO stats = new StatsDTO();
1851 stats.setFileCount(dao.getFileCount(userId));
1852 Long fileSize = dao.getFileSize(userId);
1853 stats.setFileSize(fileSize);
1854 Long quota = getQuota(userId);
1855 Long quotaLeft = quota - fileSize;
1856 stats.setQuotaLeftSize(quotaLeft);
1861 * @see gr.ebs.gss.server.ejb.ExternalAPI#getVersions(java.lang.Long, java.lang.Long)
1864 public List<FileBodyDTO> getVersions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1866 throw new ObjectNotFoundException("No user specified");
1868 throw new ObjectNotFoundException("No file specified");
1869 User user = dao.getEntityById(User.class, userId);
1870 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
1871 if(!header.hasReadPermission(user))
1872 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1873 List<FileBodyDTO> result = new LinkedList<FileBodyDTO>();
1874 for(int i = header.getBodies().size()-1 ; i>=0; i--)
1875 result.add(header.getBodies().get(i).getDTO());
1880 * @see gr.ebs.gss.server.ejb.ExternalAPI#removeVersion(java.lang.Long, java.lang.Long, java.lang.Long)
1883 public void removeVersion(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
1885 throw new ObjectNotFoundException("No user specified");
1887 throw new ObjectNotFoundException("No file specified");
1889 throw new ObjectNotFoundException("No body specified");
1890 User user = dao.getEntityById(User.class, userId);
1891 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
1892 if(!header.hasWritePermission(user))
1893 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1894 FileBody body = dao.getEntityById(FileBody.class, bodyId);
1895 if(body.equals(header.getCurrentBody())){
1897 if(header.getBodies().size() == 1)
1898 throw new InsufficientPermissionsException("You cant delete this version, Delete file instead!");
1899 for(FileBody b : header.getBodies())
1900 if(b.getVersion() == body.getVersion()-1)
1901 header.setCurrentBody(b);
1903 final File fileContents = new File(body.getStoredFilePath());
1904 if (!fileContents.delete())
1905 logger.error("Could not delete file " + body.getStoredFilePath());
1906 header.getBodies().remove(body);
1912 public void restoreVersion(Long userId, Long fileId, int version) throws ObjectNotFoundException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1914 throw new ObjectNotFoundException("No user specified");
1916 throw new ObjectNotFoundException("No file specified");
1917 User user = dao.getEntityById(User.class, userId);
1918 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
1919 if(!header.hasWritePermission(user))
1920 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1921 FileBody body = dao.getFileVersion(fileId, version);
1922 final File fileContents = new File(body.getStoredFilePath());
1925 updateFileContents(userId, fileId, body.getMimeType(), new FileInputStream(fileContents) );
1926 } catch (FileNotFoundException e) {
1927 throw new GSSIOException(e);
1933 * @see gr.ebs.gss.server.ejb.ExternalAPI#removeOldVersions(java.lang.Long, java.lang.Long)
1936 public void removeOldVersions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1938 throw new ObjectNotFoundException("No user specified");
1940 throw new ObjectNotFoundException("No file specified");
1941 User user = dao.getEntityById(User.class, userId);
1942 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
1943 if(!header.hasWritePermission(user))
1944 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1945 Iterator<FileBody> it = header.getBodies().iterator();
1946 while(it.hasNext()){
1947 FileBody body = it.next();
1948 if(!body.equals(header.getCurrentBody())){
1949 final File fileContents = new File(body.getStoredFilePath());
1950 if (!fileContents.delete())
1951 logger.error("Could not delete file " + body.getStoredFilePath());
1956 header.getCurrentBody().setVersion(1);
1961 * @see gr.ebs.gss.server.ejb.ExternalAPI#toggleFileVersioning(java.lang.Long, java.lang.Long, boolean)
1964 public void toggleFileVersioning(Long userId, Long fileId, boolean versioned) throws ObjectNotFoundException, InsufficientPermissionsException {
1966 throw new ObjectNotFoundException("No user specified");
1968 throw new ObjectNotFoundException("No file specified");
1969 User user = dao.getEntityById(User.class, userId);
1970 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
1971 if(!header.hasWritePermission(user))
1972 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1973 if(!header.isVersioned() == versioned){
1974 if(header.isVersioned())
1975 removeOldVersions(userId, fileId);
1976 header.setVersioned(versioned);
1982 * Gets the quota left for specified userId
1986 private Long getQuotaLeft(Long userId){
1987 Long fileSize = dao.getFileSize(userId);
1988 Long quota = getQuota(userId);
1989 return quota - fileSize;
1993 * Gets the quota for specified userId
1997 private Long getQuota(@SuppressWarnings("unused") Long userId){
1998 Long quota = getConfiguration().getLong("quota", new Long(52428800L));
2002 public void rebuildSolrIndex() {
2003 MessageProducer sender = null;
2004 Session session = null;
2005 Connection qConn = null;
2007 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
2008 DocumentBuilder db = dbf.newDocumentBuilder();
2009 Document doc = db.newDocument();
2010 Node root = doc.createElement("delete");
2011 doc.appendChild(root);
2012 Node queryNode = doc.createElement("query");
2013 root.appendChild(queryNode);
2014 queryNode.appendChild(doc.createTextNode("*:*"));
2016 TransformerFactory fact = TransformerFactory.newInstance();
2017 Transformer trans = fact.newTransformer();
2018 trans.setOutputProperty(OutputKeys.INDENT, "yes");
2019 StringWriter sw = new StringWriter();
2020 StreamResult sr = new StreamResult(sw);
2021 DOMSource source = new DOMSource(doc);
2022 trans.transform(source, sr);
2023 logger.debug(sw.toString());
2025 HttpClient httpClient = new HttpClient();
2026 PostMethod method = new PostMethod(getConfiguration().getString("solrUpdateUrl"));
2027 method.setRequestEntity(new StringRequestEntity(sw.toString()));
2030 String response = null;
2032 statusCode = httpClient.executeMethod(method);
2033 logger.debug("HTTP status: " + statusCode);
2034 response = method.getResponseBodyAsString();
2035 logger.debug(response);
2037 if (statusCode != 200 && retryCount < 3)
2039 Thread.sleep(10000); //Give Solr a little time to be available
2040 } catch (InterruptedException e) {
2042 } while (statusCode != 200 && retryCount < 3);
2043 method.releaseConnection();
2044 if (statusCode != 200)
2045 throw new EJBException("Cannot clear Solr index. Solr response is:\n" + response);
2046 List<Long> fileIds = dao.getAllFileIds();
2048 Context jndiCtx = new InitialContext();
2049 ConnectionFactory factory = (QueueConnectionFactory) jndiCtx.lookup("java:/JmsXA");
2050 Queue queue = (Queue) jndiCtx.lookup("queue/gss-indexingQueue");
2051 qConn = factory.createConnection();
2052 session = qConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
2053 sender = session.createProducer(queue);
2055 for (Long id : fileIds) {
2056 MapMessage map = session.createMapMessage();
2057 map.setObject("id", id);
2058 map.setBoolean("delete", false);
2061 sendOptimize(httpClient, 0);
2062 } catch (DOMException e) {
2063 throw new EJBException(e);
2064 } catch (TransformerConfigurationException e) {
2065 throw new EJBException(e);
2066 } catch (IllegalArgumentException e) {
2067 throw new EJBException(e);
2068 } catch (HttpException e) {
2069 throw new EJBException(e);
2070 } catch (UnsupportedEncodingException e) {
2071 throw new EJBException(e);
2072 } catch (ParserConfigurationException e) {
2073 throw new EJBException(e);
2074 } catch (TransformerException e) {
2075 throw new EJBException(e);
2076 } catch (IOException e) {
2077 throw new EJBException(e);
2078 } catch (NamingException e) {
2079 throw new EJBException(e);
2080 } catch (JMSException e) {
2081 throw new EJBException(e);
2087 if (session != null)
2092 catch (JMSException e) {
2099 * Sends a optimize message to the solr server
2102 * @param retryCount If the commit fails, it is retried three times. This parameter is passed in the recursive
2103 * calls to stop the recursion
2104 * @throws UnsupportedEncodingException
2105 * @throws IOException
2106 * @throws HttpException
2108 private void sendOptimize(HttpClient httpClient, int retryCount) throws UnsupportedEncodingException, IOException, HttpException {
2109 PostMethod method = null;
2111 logger.debug("Optimize retry: " + retryCount);
2112 method = new PostMethod(getConfiguration().getString("solrUpdateUrl"));
2113 method.setRequestEntity(new StringRequestEntity("<optimize/>", "text/xml", "iso8859-1"));
2114 int statusCode = httpClient.executeMethod(method);
2115 logger.debug("HTTP status: " + statusCode);
2116 String response = method.getResponseBodyAsString();
2117 logger.debug(response);
2118 if (statusCode != 200 && retryCount < 2) {
2120 Thread.sleep(10000); //Give Solr a little time to be available
2121 } catch (InterruptedException e) {
2123 sendOptimize(httpClient, retryCount + 1);
2128 method.releaseConnection();
2132 public FileHeaderDTO createFile(Long userId, Long folderId, String name, String mimeType, File fileObject)
2133 throws DuplicateNameException, ObjectNotFoundException, GSSIOException,
2134 InsufficientPermissionsException, QuotaExceededException {
2137 throw new ObjectNotFoundException("No user specified");
2138 if (folderId == null)
2139 throw new ObjectNotFoundException("No folder specified");
2140 String contentType = mimeType;
2141 if (StringUtils.isEmpty(mimeType))
2142 contentType = DEFAULT_MIME_TYPE;
2143 if (StringUtils.isEmpty(name))
2144 throw new ObjectNotFoundException("No file name specified");
2145 if (dao.existsFolderOrFile(folderId, name))
2146 throw new DuplicateNameException("A folder or file with the name '" + name +
2147 "' already exists at this level");
2149 // Do the actual work.
2150 Folder parent = null;
2152 parent = dao.getEntityById(Folder.class, folderId);
2153 } catch (final ObjectNotFoundException onfe) {
2154 // Supply a more accurate problem description.
2155 throw new ObjectNotFoundException("Parent folder not found");
2157 final User owner = dao.getEntityById(User.class, userId);
2158 if (!parent.hasWritePermission(owner))
2159 throw new InsufficientPermissionsException("You don't have the permissions to write to this folder");
2160 final FileHeader file = new FileHeader();
2162 parent.addFile(file);
2163 // set file owner to folder owner
2164 file.setOwner(parent.getOwner());
2166 final Date now = new Date();
2167 final AuditInfo auditInfo = new AuditInfo();
2168 auditInfo.setCreatedBy(owner);
2169 auditInfo.setCreationDate(now);
2170 auditInfo.setModifiedBy(owner);
2171 auditInfo.setModificationDate(now);
2172 file.setAuditInfo(auditInfo);
2173 // TODO set the proper versioning flag on creation
2174 file.setVersioned(false);
2176 for (final Permission p : parent.getPermissions()) {
2177 final Permission permission = new Permission();
2178 permission.setGroup(p.getGroup());
2179 permission.setUser(p.getUser());
2180 permission.setRead(p.getRead());
2181 permission.setWrite(p.getWrite());
2182 permission.setModifyACL(p.getModifyACL());
2183 file.addPermission(permission);
2186 // Create the file body.
2188 createFileBody(name, contentType, fileObject, file, auditInfo, owner);
2189 } catch (FileNotFoundException e) {
2190 throw new GSSIOException(e);
2193 indexFile(file.getId(), false);
2195 return file.getDTO();
2199 * @see gr.ebs.gss.server.ejb.ExternalAPI#updateFileContents(java.lang.Long, java.lang.Long, java.lang.String, java.io.InputStream)
2201 public FileHeaderDTO updateFileContents(Long userId, Long fileId, String mimeType, File fileObject) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
2203 throw new ObjectNotFoundException("No user specified");
2205 throw new ObjectNotFoundException("No file specified");
2206 String contentType = mimeType;
2208 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
2210 // if no mime type or the generic mime type is defined by the client, then try to identify it from the filename extension
2211 if (StringUtils.isEmpty(mimeType) || "application/octet-stream".equals(mimeType)
2212 || "application/download".equals(mimeType) || "application/force-download".equals(mimeType)
2213 || "octet/stream".equals(mimeType) || "application/unknown".equals(mimeType))
2214 contentType = identifyMimeType(file.getName());
2216 final User owner = dao.getEntityById(User.class, userId);
2217 if (!file.hasWritePermission(owner))
2218 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2219 final Date now = new Date();
2220 final AuditInfo auditInfo = new AuditInfo();
2221 auditInfo.setCreatedBy(owner);
2222 auditInfo.setCreationDate(now);
2223 auditInfo.setModifiedBy(owner);
2224 auditInfo.setModificationDate(now);
2226 createFileBody(file.getName(), contentType, fileObject, file, auditInfo, owner);
2227 } catch (FileNotFoundException e) {
2228 throw new GSSIOException(e);
2231 indexFile(fileId, false);
2232 return file.getDTO();
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 {
2274 long currentTotalSize = 0;
2275 if (!header.isVersioned() && header.getCurrentBody() != null && header.getBodies() != null)
2276 currentTotalSize = header.getTotalSize();
2277 Long quotaLeft = getQuotaLeft(header.getOwner().getId());
2278 if(quotaLeft < uploadedFile.length()-currentTotalSize) {
2279 uploadedFile.delete();
2280 throw new QuotaExceededException("Not enough free space available");
2283 FileBody body = new FileBody();
2285 // if no mime type or the generic mime type is defined by the client, then try to identify it from the filename extension
2286 if (StringUtils.isEmpty(mimeType) || "application/octet-stream".equals(mimeType)
2287 || "application/download".equals(mimeType) || "application/force-download".equals(mimeType)
2288 || "octet/stream".equals(mimeType) || "application/unknown".equals(mimeType))
2289 body.setMimeType(identifyMimeType(name));
2291 body.setMimeType(mimeType);
2292 body.setAuditInfo(auditInfo);
2293 body.setFileSize(uploadedFile.length());
2294 body.setOriginalFilename(name);
2295 body.setStoredFilePath(uploadedFile.getAbsolutePath());
2296 //CLEAR OLD VERSION IF FILE IS NOT VERSIONED AND GETS UPDATED
2297 if(!header.isVersioned() && header.getCurrentBody() != null){
2298 header.setCurrentBody(null);
2299 if (header.getBodies() != null) {
2300 Iterator<FileBody> it = header.getBodies().iterator();
2301 while(it.hasNext()){
2302 FileBody bo = it.next();
2303 File fileContents = new File(bo.getStoredFilePath());
2304 if (!fileContents.delete())
2305 logger.error("Could not delete file " + bo.getStoredFilePath());
2313 header.addBody(body);
2319 @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
2320 public File uploadFile(InputStream stream, Long userId) throws IOException, ObjectNotFoundException {
2322 throw new ObjectNotFoundException("No user specified");
2323 User owner = dao.getEntityById(User.class, userId);
2325 throw new ObjectNotFoundException("No user specified");
2326 long start = 0, end = 0;
2327 if (logger.isDebugEnabled())
2328 start = System.currentTimeMillis();
2329 File result = new File(generateRepositoryFilePath());
2331 final FileOutputStream output = new FileOutputStream(result);
2332 final byte[] buffer = new byte[UPLOAD_BUFFER_SIZE];
2335 while (-1 != (n = stream.read(buffer)))
2336 output.write(buffer, 0, n);
2339 } catch (IOException e) {
2340 if (!result.delete())
2341 logger.warn("Could not delete " + result.getPath());
2344 if (logger.isDebugEnabled()) {
2345 end = System.currentTimeMillis();
2346 logger.debug("Time to upload: " + (end - start) + " (msec)");
2352 public void createFileUploadProgress(Long userId, String filename, Long bytesTransfered, Long fileSize) throws ObjectNotFoundException{
2355 throw new ObjectNotFoundException("No user specified");
2356 User user = dao.getEntityById(User.class, userId);
2357 FileUploadStatus status = dao.getFileUploadStatus(userId, filename);
2359 status = new FileUploadStatus();
2360 status.setOwner(user);
2361 status.setFilename(filename);
2362 status.setBytesUploaded(bytesTransfered);
2363 status.setFileSize(fileSize);
2367 status.setBytesUploaded(bytesTransfered);
2368 status.setFileSize(fileSize);
2374 public void removeFileUploadProgress(Long userId, String filename) throws ObjectNotFoundException{
2376 throw new ObjectNotFoundException("No user specified");
2377 FileUploadStatus status = dao.getFileUploadStatus(userId, filename);
2383 public FileUploadStatus getFileUploadStatus(Long userId, String fileName) {
2384 return dao.getFileUploadStatus(userId, fileName);
2388 public FolderDTO getFolderWithSubfolders(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
2390 throw new ObjectNotFoundException("No user specified");
2391 if (folderId == null)
2392 throw new ObjectNotFoundException("No folder specified");
2393 final User user = dao.getEntityById(User.class, userId);
2394 final Folder folder = dao.getEntityById(Folder.class, folderId);
2395 // Check permissions
2396 if (!folder.hasReadPermission(user))
2397 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
2398 List<FolderDTO> subfolders = new ArrayList<FolderDTO>();
2399 if (folder.hasReadPermission(user))
2400 for (Folder f : folder.getSubfolders())
2401 if (f.hasReadPermission(user) && !f.isDeleted())
2402 subfolders.add(f.getDTO());
2403 FolderDTO result = folder.getDTO();
2404 result.setSubfolders(subfolders);
2405 return folder.getDTO();
2409 public FolderDTO getFolderWithSubfolders(Long userId, Long callingUserId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
2411 throw new ObjectNotFoundException("No user specified");
2412 if (folderId == null)
2413 throw new ObjectNotFoundException("No folder specified");
2414 User user = dao.getEntityById(User.class, callingUserId);
2415 Folder folder = dao.getEntityById(Folder.class, folderId);
2416 // Check permissions
2417 if (!folder.hasReadPermission(user))
2418 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
2420 FolderDTO result = folder.getDTO();
2421 result.setSubfolders(getSharedSubfolders(userId, callingUserId, folder.getId()));
2426 public FileBodyDTO getFileVersion(Long userId, Long fileId, int version)
2427 throws ObjectNotFoundException, InsufficientPermissionsException {
2429 throw new ObjectNotFoundException("No user specified");
2431 throw new ObjectNotFoundException("No file specified");
2433 throw new ObjectNotFoundException("No valid version specified");
2434 User user = dao.getEntityById(User.class, userId);
2435 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
2436 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
2437 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2438 FileBody body = dao.getFileVersion(fileId, version);
2439 return body.getDTO();
2443 public User updateUserPolicyAcceptance(Long userId, boolean isAccepted) throws ObjectNotFoundException {
2445 throw new ObjectNotFoundException("No user specified");
2446 User user = dao.getEntityById(User.class, userId);
2447 user.setAcceptedPolicy(isAccepted);
2452 public void updateAccounting(User user, Date date, long bandwidthDiff) {
2453 dao.updateAccounting(user, date, bandwidthDiff);
2457 public boolean canReadFolder(Long userId, Long folderId) throws ObjectNotFoundException {
2459 throw new ObjectNotFoundException("No user specified");
2460 if (folderId == null)
2461 throw new ObjectNotFoundException("No folder specified");
2462 User user = dao.getEntityById(User.class, userId);
2463 Folder folder = dao.getEntityById(Folder.class, folderId);
2464 // Check permissions
2465 if (!folder.hasReadPermission(user))