2 * Copyright 2007, 2008, 2009, 2010 Electronic Business Systems Ltd.
4 * This file is part of GSS.
6 * GSS is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GSS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GSS. If not, see <http://www.gnu.org/licenses/>.
19 package gr.ebs.gss.server.ejb;
21 import static gr.ebs.gss.server.configuration.GSSConfigurationFactory.getConfiguration;
22 import gr.ebs.gss.client.exceptions.DuplicateNameException;
23 import gr.ebs.gss.client.exceptions.GSSIOException;
24 import gr.ebs.gss.client.exceptions.InsufficientPermissionsException;
25 import gr.ebs.gss.client.exceptions.InvitationUsedException;
26 import gr.ebs.gss.client.exceptions.ObjectNotFoundException;
27 import gr.ebs.gss.client.exceptions.QuotaExceededException;
28 import gr.ebs.gss.server.domain.AuditInfo;
29 import gr.ebs.gss.server.domain.FileBody;
30 import gr.ebs.gss.server.domain.FileHeader;
31 import gr.ebs.gss.server.domain.FileTag;
32 import gr.ebs.gss.server.domain.FileUploadStatus;
33 import gr.ebs.gss.server.domain.Folder;
34 import gr.ebs.gss.server.domain.Group;
35 import gr.ebs.gss.server.domain.Invitation;
36 import gr.ebs.gss.server.domain.Nonce;
37 import gr.ebs.gss.server.domain.Permission;
38 import gr.ebs.gss.server.domain.User;
39 import gr.ebs.gss.server.domain.UserClass;
40 import gr.ebs.gss.server.domain.UserLogin;
41 import gr.ebs.gss.server.domain.dto.FileBodyDTO;
42 import gr.ebs.gss.server.domain.dto.FileHeaderDTO;
43 import gr.ebs.gss.server.domain.dto.FolderDTO;
44 import gr.ebs.gss.server.domain.dto.GroupDTO;
45 import gr.ebs.gss.server.domain.dto.PermissionDTO;
46 import gr.ebs.gss.server.domain.dto.StatsDTO;
47 import gr.ebs.gss.server.domain.dto.UserDTO;
50 import java.io.FileInputStream;
51 import java.io.FileNotFoundException;
52 import java.io.FileOutputStream;
53 import java.io.IOException;
54 import java.io.InputStream;
55 import java.io.UnsupportedEncodingException;
56 import java.net.MalformedURLException;
57 import java.util.ArrayList;
58 import java.util.Date;
59 import java.util.Iterator;
60 import java.util.LinkedHashSet;
61 import java.util.LinkedList;
62 import java.util.List;
63 import java.util.Locale;
64 import java.util.Random;
66 import java.util.StringTokenizer;
69 import javax.ejb.EJBException;
70 import javax.ejb.EJBTransactionRolledbackException;
71 import javax.ejb.Stateless;
72 import javax.ejb.TransactionAttribute;
73 import javax.ejb.TransactionAttributeType;
74 import javax.jms.Connection;
75 import javax.jms.ConnectionFactory;
76 import javax.jms.JMSException;
77 import javax.jms.MapMessage;
78 import javax.jms.MessageProducer;
79 import javax.jms.Queue;
80 import javax.jms.QueueConnectionFactory;
81 import javax.jms.Session;
82 import javax.naming.Context;
83 import javax.naming.InitialContext;
84 import javax.naming.NamingException;
85 import javax.persistence.PersistenceException;
87 import org.apache.commons.lang.StringUtils;
88 import org.apache.commons.logging.Log;
89 import org.apache.commons.logging.LogFactory;
90 import org.apache.solr.client.solrj.SolrQuery;
91 import org.apache.solr.client.solrj.SolrServerException;
92 import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
93 import org.apache.solr.client.solrj.request.ContentStreamUpdateRequest;
94 import org.apache.solr.client.solrj.response.QueryResponse;
95 import org.apache.solr.common.SolrDocument;
96 import org.apache.solr.common.SolrDocumentList;
97 import org.apache.solr.common.SolrException;
98 import org.apache.solr.common.SolrInputDocument;
99 import org.hibernate.exception.ConstraintViolationException;
101 import com.novell.ldap.LDAPAttribute;
102 import com.novell.ldap.LDAPAttributeSet;
103 import com.novell.ldap.LDAPConnection;
104 import com.novell.ldap.LDAPEntry;
105 import com.novell.ldap.LDAPException;
108 * The concrete implementation of the ExternalAPI interface.
113 public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
115 * The default MIME type for files without an explicit one.
117 private static final String DEFAULT_MIME_TYPE = "application/octet-stream";
120 * The size of the buffer that is used to temporarily store chunks of
121 * uploaded files, while storing them to the file repository.
123 private static final int UPLOAD_BUFFER_SIZE = 1024 * 4;
128 private static Log logger = LogFactory.getLog(ExternalAPIBean.class);
131 * Injected reference to the GSSDAO data access facade.
138 * A cached random number generator for creating unique filenames.
140 private static Random random = new Random();
143 * Mark the folder and all of its parent folders as modified from the specified user.
145 private void touchParentFolders(Folder folder, User user, Date date) {
148 AuditInfo ai = f.getAuditInfo();
149 ai.setModifiedBy(user);
150 ai.setModificationDate(date);
156 private Long getRootFolderId(Long userId) throws ObjectNotFoundException {
158 throw new ObjectNotFoundException("No user specified");
159 return dao.getRootFolderId(userId);
163 public FolderDTO getRootFolder(Long userId) throws ObjectNotFoundException {
165 throw new ObjectNotFoundException("No user specified");
166 Folder folder = dao.getRootFolder(userId);
167 return folder.getDTO();
171 public FolderDTO getFolder(final Long userId, final Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
173 throw new ObjectNotFoundException("No user specified");
174 if (folderId == null)
175 throw new ObjectNotFoundException("No folder specified");
176 final User user = dao.getEntityById(User.class, userId);
177 final Folder folder = dao.getEntityById(Folder.class, folderId);
179 if (!folder.hasReadPermission(user))
180 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
181 return folder.getDTO();
185 public User getUser(Long userId) throws ObjectNotFoundException {
187 throw new ObjectNotFoundException("No user specified");
188 return dao.getEntityById(User.class, userId);
192 public UserDTO getUserDTO(final Long userId) throws ObjectNotFoundException {
193 return getUser(userId).getDTO();
197 public GroupDTO getGroup(final Long groupId) throws ObjectNotFoundException {
199 throw new ObjectNotFoundException("No group specified");
200 final Group group = dao.getEntityById(Group.class, groupId);
201 return group.getDTO();
205 public GroupDTO getGroup(Long userId, String name) throws ObjectNotFoundException {
207 throw new ObjectNotFoundException("No user specified");
209 throw new ObjectNotFoundException("No group specified");
210 User user = dao.getEntityById(User.class, userId);
211 List<Group> groups = user.getGroupsSpecified();
212 for (Group group: groups)
213 if (group.getName().equals(name))
214 return group.getDTO();
215 throw new ObjectNotFoundException("Group " + name + " not found");
219 public List<GroupDTO> getGroups(final Long userId) throws ObjectNotFoundException {
221 throw new ObjectNotFoundException("No user specified");
222 final List<Group> groups = dao.getGroups(userId);
223 final List<GroupDTO> result = new ArrayList<GroupDTO>();
224 for (final Group g : groups)
225 result.add(g.getDTO());
230 public List<FileHeaderDTO> getFiles(Long userId, Long folderId, boolean ignoreDeleted)
231 throws ObjectNotFoundException, InsufficientPermissionsException {
234 throw new ObjectNotFoundException("No user specified");
235 if (folderId == null)
236 throw new ObjectNotFoundException("No folder specified");
237 User user = dao.getEntityById(User.class, userId);
238 Folder folder = dao.getEntityById(Folder.class, folderId);
239 if (!folder.hasReadPermission(user))
240 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
241 // Do the actual work.
242 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
243 List<FileHeader> files = dao.getFiles(folderId, userId, ignoreDeleted);
244 for (FileHeader f : files)
245 result.add(f.getDTO());
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 FolderDTO 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 return createFolder(name, parent, creator);
297 * Create a new folder with the provided name, parent and owner.
302 * @return the new folder
304 private FolderDTO 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);
320 touchParentFolders(folder, auditInfo.getModifiedBy(), auditInfo.getModificationDate());
323 for (Permission p : parent.getPermissions()) {
324 Permission permission = new Permission();
325 permission.setGroup(p.getGroup());
326 permission.setUser(p.getUser());
327 permission.setRead(p.getRead());
328 permission.setWrite(p.getWrite());
329 permission.setModifyACL(p.getModifyACL());
330 folder.addPermission(permission);
333 Permission permission = new Permission();
334 permission.setUser(creator);
335 permission.setRead(true);
336 permission.setWrite(true);
337 permission.setModifyACL(true);
338 folder.addPermission(permission);
342 folder.setReadForAll(parent.isReadForAll());
345 return folder.getDTO();
349 public void deleteFolder(final Long userId, final Long folderId) throws InsufficientPermissionsException, ObjectNotFoundException {
352 throw new ObjectNotFoundException("No user specified");
353 if (folderId == null)
354 throw new ObjectNotFoundException("No folder specified");
356 // Do the actual work.
357 final Folder folder = dao.getEntityById(Folder.class, folderId);
358 final Folder parent = folder.getParent();
360 throw new ObjectNotFoundException("Deleting the root folder is not allowed");
361 final User user = dao.getEntityById(User.class, userId);
362 if (!folder.hasDeletePermission(user)) {
363 logger.info("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
364 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
366 removeSubfolderFiles(folder);
367 parent.removeSubfolder(folder);
369 touchParentFolders(parent, user, new Date());
373 * Traverses the folder and deletes all actual files (file system)
374 * regardless of permissions
378 private void removeSubfolderFiles(Folder folder) {
379 //remove files for all subfolders
380 for (Folder subfolder:folder.getSubfolders())
381 removeSubfolderFiles(subfolder);
382 //remove this folder's file bodies (actual files)
383 for (FileHeader file:folder.getFiles()) {
384 for (FileBody body:file.getBodies())
385 deleteActualFile(body.getStoredFilePath());
386 indexFile(file.getId(), true);
391 @SuppressWarnings("unchecked")
392 public List<FolderDTO> getSubfolders(Long userId, Long folderId)
393 throws ObjectNotFoundException, InsufficientPermissionsException {
395 throw new ObjectNotFoundException("No user specified");
396 if (folderId == null)
397 throw new ObjectNotFoundException("No folder specified");
398 User user = dao.getEntityById(User.class, userId);
399 Folder folder = dao.getEntityById(Folder.class, folderId);
400 if (!folder.hasReadPermission(user))
401 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
402 List<FolderDTO> result = new ArrayList<FolderDTO>();
403 if (folder.hasReadPermission(user))
404 for (Folder f : folder.getSubfolders())
405 if (f.hasReadPermission(user) && !f.isDeleted())
406 result.add(f.getDTO());
411 public FolderDTO updateFolder(Long userId, Long folderId, String folderName,
413 Set<PermissionDTO> permissions)
414 throws InsufficientPermissionsException, ObjectNotFoundException,
415 DuplicateNameException {
419 throw new ObjectNotFoundException("No user specified");
420 if (folderId == null)
421 throw new ObjectNotFoundException("No folder specified");
423 Folder folder = dao.getEntityById(Folder.class, folderId);
424 User user = dao.getEntityById(User.class, userId);
425 if (folderName != null && !folder.hasWritePermission(user))
426 throw new InsufficientPermissionsException("You don't have the necessary permissions");
427 if(permissions != null && !permissions.isEmpty() && !folder.hasModifyACLPermission(user))
428 throw new InsufficientPermissionsException("You don't have the necessary permissions");
429 // Check permissions for making file public.
430 if (readForAll != null && !user.equals(folder.getOwner()))
431 throw new InsufficientPermissionsException("Only the owner can make a folder public or not public");
433 Folder parent = folder.getParent();
434 if (folderName != null) {
436 if (!folder.getName().equals(folderName) && dao.existsFolderOrFile(parent.getId(), folderName))
437 throw new DuplicateNameException("A folder or file with the name '" + folderName + "' already exists at this level");
439 // Do the actual modification.
440 folder.setName(folderName);
442 if (permissions != null)
443 setFolderPermissions(user, folder, permissions);
444 if (readForAll != null)
445 setFolderReadForAll(user, folder, readForAll);
446 folder.getAuditInfo().setModificationDate(new Date());
447 folder.getAuditInfo().setModifiedBy(user);
449 touchParentFolders(folder, user, new Date());
450 return folder.getDTO();
454 public void createGroup(final Long userId, final String name) throws ObjectNotFoundException, DuplicateNameException {
457 throw new ObjectNotFoundException("No user specified");
458 if (StringUtils.isEmpty(name))
459 throw new ObjectNotFoundException("New group name is empty");
460 if (name.indexOf('/')>=0)
461 throw new IllegalArgumentException("Character '/' is not allowed in group name");
462 if (dao.existsGroup(userId, name))
463 throw new DuplicateNameException("A group with the name '" + name + "' already exists");
465 // TODO: Check permissions
467 final User owner = dao.getEntityById(User.class, userId);
469 // Do the actual work.
470 owner.createGroup(name);
474 public void deleteGroup(final Long userId, final Long groupId) throws ObjectNotFoundException, InsufficientPermissionsException {
477 throw new ObjectNotFoundException("No user specified");
479 throw new ObjectNotFoundException("No group specified");
481 // Do the actual work.
482 final User owner = dao.getEntityById(User.class, userId);
483 final Group group = dao.getEntityById(Group.class, groupId);
484 final Date now = new Date();
485 // Only delete the group if actually owned by the user.
486 if (group.getOwner().equals(owner)) {
487 List<Folder> folders = dao.getFoldersPermittedForGroup(userId, groupId);
488 for (Folder f : folders){
489 f.getPermissions().removeAll(group.getPermissions());
490 touchFolder(f, owner, now);
491 for(FileHeader file : f.getFiles()){
492 file.getPermissions().removeAll(group.getPermissions());
493 touchFile(file, owner, now);
496 List<FileHeader> files = dao.getFilesPermittedForGroup(userId, groupId);
497 for(FileHeader h : files){
498 h.getPermissions().removeAll(group.getPermissions());
499 touchFile(h, owner, now);
501 owner.removeSpecifiedGroup(group);
504 else throw new InsufficientPermissionsException("You are not the owner of this group");
508 public FileHeaderDTO createFile(Long userId, Long folderId, String name, String mimeType, InputStream stream)
509 throws DuplicateNameException, ObjectNotFoundException, GSSIOException,
510 InsufficientPermissionsException, QuotaExceededException {
513 file = uploadFile(stream, userId);
514 } catch ( IOException ioe) {
515 // Supply a more accurate problem description.
516 throw new GSSIOException("Problem creating file",ioe);
518 return createFile(userId, folderId, name, mimeType, file.length(), file.getAbsolutePath());
522 * @see gr.ebs.gss.server.ejb.ExternalAPIRemote#indexFile(java.lang.Long, boolean)
525 public void indexFile(Long fileId, boolean delete) {
526 Connection qConn = null;
527 Session session = null;
528 MessageProducer sender = null;
530 Context jndiCtx = new InitialContext();
531 ConnectionFactory factory = (QueueConnectionFactory) jndiCtx.lookup("java:/JmsXA");
532 Queue queue = (Queue) jndiCtx.lookup("queue/gss-indexingQueue");
533 qConn = factory.createConnection();
534 session = qConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
535 sender = session.createProducer(queue);
537 MapMessage map = session.createMapMessage();
538 map.setObject("id", fileId);
539 map.setBoolean("delete", delete);
542 catch (NamingException e) {
543 logger.error("Index was not updated: ", e);
545 catch (JMSException e) {
546 logger.error("Index was not updated: ", e);
557 catch (JMSException e) {
566 * A helper method that generates a unique file path for a stored file. The
567 * files are stored using random hash names that are distributed evenly in
568 * a 2-level tree of subdirectories named after the first two hex characters
569 * in the name. For example, file ab1234cd5769f will be stored in the path
570 * /file-repository-root/a/b/ab1234cd5769f. The directories will be created
571 * if they don't already exist.
573 * @return a unique new file path
575 private String generateRepositoryFilePath() {
576 String filename = Long.toHexString(random.nextLong());
577 String fileRepositoryPath = getConfiguration().getString("fileRepositoryPath","/tmp");
578 File root = new File(fileRepositoryPath);
581 File firstFolder = new File(root + File.separator + filename.substring(0, 1));
582 if (!firstFolder.exists())
584 File secondFolder = new File(firstFolder + File.separator + filename.substring(1, 2));
585 if (!secondFolder.exists())
586 secondFolder.mkdir();
587 return secondFolder + File.separator + filename;
591 public void deleteFile(final Long userId, final Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
594 throw new ObjectNotFoundException("No user specified");
596 throw new ObjectNotFoundException("No file specified");
598 // Do the actual work.
599 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
600 final Folder parent = file.getFolder();
602 throw new ObjectNotFoundException("The specified file has no parent folder");
603 final User user = dao.getEntityById(User.class, userId);
604 if (!file.hasDeletePermission(user))
605 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
606 for (final FileBody body : file.getBodies())
607 deleteActualFile(body.getStoredFilePath());
609 touchParentFolders(parent, user, new Date());
610 indexFile(fileId, true);
614 public void deleteActualFile(String path) {
617 File file = new File(path);
619 logger.error("Could not delete file " + path);
623 public void createTag(final Long userId, final Long fileHeaderId, final String tag) throws ObjectNotFoundException {
625 throw new ObjectNotFoundException("No user specified");
626 if (fileHeaderId == null)
627 throw new ObjectNotFoundException("No file specified");
628 if (StringUtils.isEmpty(tag))
629 throw new ObjectNotFoundException("Tag is empty");
631 final User user = dao.getEntityById(User.class, userId);
632 final FileHeader fh = dao.getEntityById(FileHeader.class, fileHeaderId);
633 final Folder parent = fh.getFolder();
635 throw new ObjectNotFoundException("The specified file has no parent folder");
636 user.addTag(fh, tag);
637 touchParentFolders(parent, user, new Date());
641 public Set<String> getUserTags(final Long userId) throws ObjectNotFoundException {
642 return dao.getUserTags(userId);
646 public void updateFile(Long userId, Long fileId, String name,
647 String tagSet, Date modificationDate, Boolean versioned,
648 Boolean readForAll, Set<PermissionDTO> permissions)
649 throws DuplicateNameException, ObjectNotFoundException, InsufficientPermissionsException {
651 throw new ObjectNotFoundException("No user specified");
653 throw new ObjectNotFoundException("No file specified");
654 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
655 final Folder parent = file.getFolder();
657 throw new ObjectNotFoundException("The specified file has no parent folder");
659 User user = dao.getEntityById(User.class, userId);
660 // Check permissions for modifying the file metadata.
661 if ((name != null || tagSet != null || modificationDate != null || versioned != null) && !file.hasWritePermission(user))
662 throw new InsufficientPermissionsException("User " + user.getId() + " cannot update file " + file.getName() + "(" + file.getId() + ")");
663 // Check permissions for making file public.
664 if (readForAll != null && !user.equals(file.getOwner()))
665 throw new InsufficientPermissionsException("Only the owner can make a file public or not public");
666 // Check permissions for modifying the ACL.
667 if(permissions != null && !permissions.isEmpty() && !file.hasModifyACLPermission(user))
668 throw new InsufficientPermissionsException("User " + user.getId() + " cannot update the permissions on file " + file.getName() + "(" + file.getId() + ")");
671 // Do plain check for file already exists.
672 // Extreme concurrency case should be caught by constraint violation later.
673 if (dao.existsFolderOrFile(parent.getId(), name)) throw new DuplicateNameException("A file or folder with the name '" + name + "' already exists");
677 if (modificationDate != null)
678 file.getAuditInfo().setModificationDate(modificationDate);
680 file.getAuditInfo().setModificationDate(new Date());
681 file.getAuditInfo().setModifiedBy(user);
683 List<FileTag> tags = file.getFileTags();
684 if (tagSet != null) {
685 Iterator<FileTag> i = tags.iterator();
686 while (i.hasNext()) {
687 FileTag tag = i.next();
694 StringTokenizer st = new StringTokenizer(tagSet, ",");
695 while (st.hasMoreTokens())
696 new FileTag(user, file, st.nextToken().trim());
698 if (versioned != null && !file.isVersioned() == versioned) {
699 if (file.isVersioned())
700 removeOldVersions(userId, fileId);
701 file.setVersioned(versioned);
703 if (readForAll != null && user.equals(file.getOwner()))
704 file.setReadForAll(readForAll);
705 if (permissions != null && !permissions.isEmpty())
706 setFilePermissions(file, permissions);
709 * Force constraint violation to manifest itself here.
710 * This should cover extreme concurrency cases that the simple check
711 * above hasn't caught.
716 catch (EJBTransactionRolledbackException e) {
717 Throwable cause = e.getCause();
718 if (cause instanceof PersistenceException && cause.getCause() instanceof ConstraintViolationException)
719 throw new DuplicateNameException("A file or folder with the name '" + name + "' already exists");
723 touchParentFolders(parent, user, new Date());
725 // Re-index the file if it was modified.
726 if (name != null || tagSet != null || (permissions != null && !permissions.isEmpty()) || readForAll != null)
727 indexFile(fileId, false);
731 public InputStream getFileContents(Long userId, Long fileId)
732 throws ObjectNotFoundException, InsufficientPermissionsException {
734 throw new ObjectNotFoundException("No user specified");
736 throw new ObjectNotFoundException("No file specified");
738 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
739 User user = dao.getEntityById(User.class, userId);
740 if (!header.hasReadPermission(user)) {
741 logger.info("User " + user.getId() + " cannot read file " + header.getName() + "(" + fileId + ")");
742 throw new InsufficientPermissionsException("You don't have the necessary permissions");
745 File f = new File(header.getCurrentBody().getStoredFilePath());
747 return new FileInputStream(f);
748 } catch (FileNotFoundException e) {
749 logger.error("Could not locate the contents of file " + f.getAbsolutePath());
750 throw new ObjectNotFoundException("The file contents could not be located");
755 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFileContents(java.lang.Long, java.lang.Long, java.lang.Long)
758 public InputStream getFileContents(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
760 throw new ObjectNotFoundException("No user specified");
762 throw new ObjectNotFoundException("No file specified");
764 throw new ObjectNotFoundException("No file specified");
766 final FileHeader header = dao.getEntityById(FileHeader.class, fileId);
767 final FileBody body = dao.getEntityById(FileBody.class, bodyId);
768 final User user = dao.getEntityById(User.class, userId);
769 if (!header.hasReadPermission(user)) {
770 logger.info("User " + user.getId() + " cannot read file " + header.getName() + "(" + fileId + ")");
771 throw new InsufficientPermissionsException("You don't have the necessary permissions");
774 File f = new File(body.getStoredFilePath());
776 return new FileInputStream(f);
777 } catch (FileNotFoundException e) {
778 logger.error("Could not locate the contents of file " + f.getAbsolutePath());
779 throw new ObjectNotFoundException("The file contents could not be located");
784 public FileHeaderDTO getFile(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
786 throw new ObjectNotFoundException("No user specified");
788 throw new ObjectNotFoundException("No file specified");
789 final User user = dao.getEntityById(User.class, userId);
790 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
791 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
792 throw new InsufficientPermissionsException("You don't have the necessary permissions");
793 return file.getDTO();
797 public FileBodyDTO getFileBody(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
799 throw new ObjectNotFoundException("No user specified");
801 throw new ObjectNotFoundException("No file specified");
802 User user = dao.getEntityById(User.class, userId);
803 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
804 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
805 throw new InsufficientPermissionsException("You don't have the necessary permissions");
806 FileBody body = dao.getEntityById(FileBody.class, bodyId);
807 return body.getDTO();
811 public Object getResourceAtPath(Long ownerId, String path, boolean ignoreDeleted)
812 throws ObjectNotFoundException {
814 throw new ObjectNotFoundException("No user specified");
815 if (StringUtils.isEmpty(path))
816 throw new ObjectNotFoundException("No path specified");
818 User owner = dao.getEntityById(User.class, ownerId);
819 List<String> pathElements = new ArrayList<String>();
820 StringTokenizer st = new StringTokenizer(path, "/");
821 while (st.hasMoreTokens())
822 pathElements.add(st.nextToken());
823 if (pathElements.size() < 1)
824 return getRootFolder(owner.getId());
825 // Store the last element, since it requires special handling.
826 String lastElement = pathElements.remove(pathElements.size() - 1);
828 Folder cursor = null;
829 Long rootFolderId = getRootFolderId(owner.getId());
830 // Traverse and verify the specified folder path.
831 for (String pathElement : pathElements) {
832 cursor = getFolder(cursor==null ? rootFolderId : cursor.getId(), pathElement);
833 if (cursor.isDeleted())
834 throw new ObjectNotFoundException("Folder " + cursor.getPath() + " not found");
837 // Use the lastElement to retrieve the actual resource.
838 Object resource = null;
840 FileHeaderDTO file = getFile(cursor==null ? rootFolderId : cursor.getId(), lastElement);
841 if (ignoreDeleted && file.isDeleted())
842 throw new ObjectNotFoundException("Resource not found");
844 } catch (ObjectNotFoundException e) {
845 // Perhaps the requested resource is not a file, so
846 // check for folders as well.
847 FolderDTO folder = getFolder(cursor==null ? rootFolderId : cursor.getId(), lastElement).getDTO();
848 if (ignoreDeleted && folder.isDeleted())
849 throw new ObjectNotFoundException("Resource not found");
856 * Retrieve a file for the specified user that has the specified name and
857 * its parent folder has id equal to folderId.
859 * @param folderId the ID of the parent folder
860 * @param name the name of the requested file
861 * @return the file found
862 * @throws ObjectNotFoundException if the specified folder or file was not
863 * found, with the exception message mentioning the precise
866 private FileHeaderDTO getFile(Long folderId, String name) throws ObjectNotFoundException {
867 if (folderId == null)
868 throw new ObjectNotFoundException("No parent folder specified");
869 if (StringUtils.isEmpty(name))
870 throw new ObjectNotFoundException("No file specified");
872 FileHeader file = dao.getFile(folderId, name);
873 return file.getDTO();
877 * Retrieve a folder for the specified user that has the specified name and
878 * its parent folder has id equal to parentId.
880 * @param parentId the ID of the parent folder
881 * @param name the name of the requested folder
882 * @return the folder found
883 * @throws ObjectNotFoundException if the specified folder or parent was not
884 * found, with the exception message mentioning the precise
887 private Folder getFolder(Long parentId, String name) throws ObjectNotFoundException {
888 if (parentId == null)
889 throw new ObjectNotFoundException("No parent folder specified");
890 if (StringUtils.isEmpty(name))
891 throw new ObjectNotFoundException("No folder specified");
893 Folder folder = dao.getFolder(parentId, name);
897 private FileHeaderDTO updateFileContents(Long userId, Long fileId, String mimeType, InputStream resourceInputStream) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
900 file = uploadFile(resourceInputStream, userId);
901 } catch ( IOException ioe) {
902 // Supply a more accurate problem description.
903 throw new GSSIOException("Problem creating file",ioe);
905 return updateFileContents(userId, fileId, mimeType, file.length(), file.getAbsolutePath());
909 public void copyFile(Long userId, Long fileId, String dest) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
911 throw new ObjectNotFoundException("No user specified");
913 throw new ObjectNotFoundException("No file specified");
914 if (StringUtils.isEmpty(dest))
915 throw new ObjectNotFoundException("No destination specified");
917 Object destination = getResourceAtPath(userId, getParentPath(dest), true);
918 if (!(destination instanceof FolderDTO))
919 throw new ObjectNotFoundException("Destination parent folder not found");
920 FolderDTO parent = (FolderDTO) destination;
921 copyFile(userId, fileId, parent.getId(), getLastElement(dest));
925 public void copyFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
927 throw new ObjectNotFoundException("No user specified");
929 throw new ObjectNotFoundException("No owner specified");
931 throw new ObjectNotFoundException("No file specified");
932 if (StringUtils.isEmpty(dest))
933 throw new ObjectNotFoundException("No destination specified");
935 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
936 if (!(destination instanceof FolderDTO))
937 throw new ObjectNotFoundException("Destination parent folder not found");
938 FolderDTO parent = (FolderDTO) destination;
939 copyFile(userId, fileId, parent.getId(), getLastElement(dest));
943 public void copyFile(Long userId, Long fileId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
945 throw new ObjectNotFoundException("No user specified");
947 throw new ObjectNotFoundException("No file specified");
949 throw new ObjectNotFoundException("No destination specified");
950 if (StringUtils.isEmpty(destName))
951 throw new ObjectNotFoundException("No destination file name specified");
953 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
954 Folder destination = dao.getEntityById(Folder.class, destId);
955 User user = dao.getEntityById(User.class, userId);
956 if (!file.hasReadPermission(user) || !destination.hasWritePermission(user))
957 throw new InsufficientPermissionsException("You don't have the necessary permissions");
958 boolean versioned = file.isVersioned();
959 int versionsNumber = file.getBodies().size();
960 FileBody oldestBody = file.getBodies().get(0);
961 assert oldestBody != null;
962 File contents = new File(oldestBody.getStoredFilePath());
964 createFile(user.getId(), destination.getId(), destName, oldestBody.getMimeType(), new FileInputStream(contents));
965 FileHeader copiedFile = dao.getFile(destination.getId(), destName);
966 copiedFile.setVersioned(versioned);
968 if (versionsNumber > 1)
969 for (int i = 1; i < versionsNumber; i++) {
970 FileBody body = file.getBodies().get(i);
972 contents = new File(body.getStoredFilePath());
973 updateFileContents(user.getId(), copiedFile.getId(), body.getMimeType(), new FileInputStream(contents));
975 List<FileTag> tags = file.getFileTags();
976 for (FileTag tag : tags)
977 createTag(userId, copiedFile.getId(), tag.getTag());
979 } catch (FileNotFoundException e) {
980 throw new ObjectNotFoundException("File contents not found for file " + contents.getAbsolutePath());
986 public void copyFolder(Long userId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
988 throw new ObjectNotFoundException("No user specified");
989 if (folderId == null)
990 throw new ObjectNotFoundException("No folder specified");
991 if (StringUtils.isEmpty(dest))
992 throw new ObjectNotFoundException("No destination specified");
994 Object destination = getResourceAtPath(userId, getParentPath(dest), true);
995 if (!(destination instanceof FolderDTO))
996 throw new ObjectNotFoundException("Destination folder not found");
997 FolderDTO parent = (FolderDTO) destination;
998 copyFolder(userId, folderId, parent.getId(), getLastElement(dest));
1002 public void copyFolder(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
1004 throw new ObjectNotFoundException("No user specified");
1005 if (folderId == null)
1006 throw new ObjectNotFoundException("No folder specified");
1008 throw new ObjectNotFoundException("No destination specified");
1009 if (StringUtils.isEmpty(destName))
1010 throw new ObjectNotFoundException("No destination folder name specified");
1011 Folder folder = dao.getEntityById(Folder.class, folderId);
1012 Folder destination = dao.getEntityById(Folder.class, destId);
1013 User user = dao.getEntityById(User.class, userId);
1014 if (!destination.hasWritePermission(user) || !folder.hasReadPermission(user))
1015 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1016 createFolder(user.getId(), destination.getId(), destName);
1020 public void copyFolderStructureToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1022 throw new ObjectNotFoundException("No user specified");
1023 if (ownerId == null)
1024 throw new ObjectNotFoundException("No owner specified");
1025 if (folderId == null)
1026 throw new ObjectNotFoundException("No folder specified");
1027 if (StringUtils.isEmpty(dest))
1028 throw new ObjectNotFoundException("No destination specified");
1030 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1031 if (!(destination instanceof FolderDTO))
1032 throw new ObjectNotFoundException("Destination folder not found");
1033 FolderDTO parent = (FolderDTO) destination;
1034 copyFolderStructure(userId, folderId, parent.getId(), getLastElement(dest));
1038 public void copyFolderStructure(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1040 throw new ObjectNotFoundException("No user specified");
1041 if (folderId == null)
1042 throw new ObjectNotFoundException("No folder specified");
1044 throw new ObjectNotFoundException("No destination specified");
1045 if (StringUtils.isEmpty(destName))
1046 throw new ObjectNotFoundException("No destination folder name specified");
1048 Folder folder = dao.getEntityById(Folder.class, folderId);
1049 Folder destination = dao.getEntityById(Folder.class, destId);
1050 final User user = dao.getEntityById(User.class, userId);
1051 // XXX: quick fix need to copy only visible items to user (Source
1053 if (!folder.getOwner().getId().equals(userId) && !folder.hasReadPermission(user))
1055 if(folder.isDeleted())//do not copy trashed folder and contents
1057 if (!destination.hasWritePermission(user) || !folder.hasReadPermission(user))
1058 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1059 createFolder(user.getId(), destination.getId(), destName);
1060 Folder createdFolder = dao.getFolder(destination.getId(), destName);
1061 List<FileHeader> files = folder.getFiles();
1063 for (FileHeader file : files)
1064 if(!file.isDeleted())
1065 copyFile(userId, file.getId(), createdFolder.getId(), file.getName());
1066 List<Folder> subFolders = folder.getSubfolders();
1067 if (subFolders != null)
1068 for (Folder sub : subFolders)
1069 if(!sub.getId().equals(createdFolder.getId()))
1070 copyFolderStructure(userId, sub.getId(), createdFolder.getId(), sub.getName());
1075 * For a provided path, remove the last element and return the rest, that is
1076 * the path of the parent folder.
1078 * @param path the specified path
1079 * @return the path of the parent folder
1080 * @throws ObjectNotFoundException if the provided string contains no path
1083 private String getParentPath(String path) throws ObjectNotFoundException {
1084 int lastDelimiter = path.lastIndexOf('/');
1085 if (lastDelimiter == 0)
1087 if (lastDelimiter == -1)
1089 throw new ObjectNotFoundException("There is no parent in the path: " + path);
1090 else if (lastDelimiter < path.length() - 1)
1091 // Return the part before the delimiter.
1092 return path.substring(0, lastDelimiter);
1094 // Remove the trailing delimiter and then recurse.
1095 String strippedTrail = path.substring(0, lastDelimiter);
1096 return getParentPath(strippedTrail);
1101 * Get the last element in a path that denotes the file or folder name.
1103 * @param path the provided path
1104 * @return the last element in the path
1106 private String getLastElement(String path) {
1107 int lastDelimiter = path.lastIndexOf('/');
1108 if (lastDelimiter == -1)
1111 else if (lastDelimiter < path.length() - 1)
1112 // Return the part after the delimiter.
1113 return path.substring(lastDelimiter + 1);
1115 // Remove the trailing delimiter and then recurse.
1116 String strippedTrail = path.substring(0, lastDelimiter);
1117 return getLastElement(strippedTrail);
1122 public void moveFileToTrash(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1124 throw new ObjectNotFoundException("No user specified");
1126 throw new ObjectNotFoundException("No file specified");
1128 // Do the actual work.
1129 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1130 Folder parent = file.getFolder();
1132 throw new ObjectNotFoundException("The specified file has no parent folder");
1133 User user = dao.getEntityById(User.class, userId);
1134 if (!file.hasDeletePermission(user))
1135 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
1137 file.setDeleted(true);
1139 touchParentFolders(parent, user, new Date());
1143 public void moveFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, InsufficientPermissionsException, QuotaExceededException {
1145 throw new ObjectNotFoundException("No user specified");
1146 if (ownerId == null)
1147 throw new ObjectNotFoundException("No owner specified");
1149 throw new ObjectNotFoundException("No file specified");
1150 if (StringUtils.isEmpty(dest))
1151 throw new ObjectNotFoundException("No destination specified");
1153 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1154 if (!(destination instanceof FolderDTO))
1155 throw new ObjectNotFoundException("Destination parent folder not found");
1156 FolderDTO parent = (FolderDTO) destination;
1157 moveFile(userId, fileId, parent.getId(), getLastElement(dest));
1161 public void moveFile(Long userId, Long fileId, Long destId, String destName) throws InsufficientPermissionsException, ObjectNotFoundException, QuotaExceededException {
1163 throw new ObjectNotFoundException("No user specified");
1165 throw new ObjectNotFoundException("No file specified");
1167 throw new ObjectNotFoundException("No destination specified");
1168 if (StringUtils.isEmpty(destName))
1169 throw new ObjectNotFoundException("No destination file name specified");
1171 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1172 Folder source = file.getFolder();
1173 Folder destination = dao.getEntityById(Folder.class, destId);
1175 User owner = dao.getEntityById(User.class, userId);
1176 if (!file.hasDeletePermission(owner) || !destination.hasWritePermission(owner))
1177 throw new InsufficientPermissionsException("User " + owner.getId() + " cannot move file " + file.getName() + "(" + file.getId() + ")");
1179 // if the destination folder belongs to another user:
1180 if (!file.getOwner().equals(destination.getOwner())) {
1181 // (a) check if the destination quota allows the move
1182 if(getQuotaLeft(destination.getOwner().getId()) < file.getTotalSize())
1183 throw new QuotaExceededException("Not enough free space available");
1184 User newOwner = destination.getOwner();
1185 // (b) if quota OK, change the owner of the file
1186 file.setOwner(newOwner);
1187 // if the file has no permission for the new owner, add it
1188 Permission ownerPermission = null;
1189 for (final Permission p : file.getPermissions())
1190 if (p.getUser() != null)
1191 if (p.getUser().equals(newOwner)) {
1192 ownerPermission = p;
1195 if (ownerPermission == null) {
1196 ownerPermission = new Permission();
1197 ownerPermission.setUser(newOwner);
1198 file.addPermission(ownerPermission);
1200 ownerPermission.setRead(true);
1201 ownerPermission.setWrite(true);
1202 ownerPermission.setModifyACL(true);
1204 // move the file to the destination folder
1205 file.setFolder(destination);
1206 touchParentFolders(source, owner, new Date());
1207 touchParentFolders(destination, owner, new Date());
1211 public void moveFolderToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, InsufficientPermissionsException, QuotaExceededException {
1213 throw new ObjectNotFoundException("No user specified");
1214 if (ownerId == null)
1215 throw new ObjectNotFoundException("No owner specified");
1216 if (folderId == null)
1217 throw new ObjectNotFoundException("No folder specified");
1218 if (StringUtils.isEmpty(dest))
1219 throw new ObjectNotFoundException("No destination specified");
1221 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1222 if (!(destination instanceof FolderDTO))
1223 throw new ObjectNotFoundException("Destination parent folder not found");
1224 FolderDTO parent = (FolderDTO) destination;
1225 moveFolder(userId, folderId, parent.getId(), getLastElement(dest));
1229 public void moveFolder(Long userId, Long folderId, Long destId, String destName)
1230 throws ObjectNotFoundException, InsufficientPermissionsException,
1231 QuotaExceededException {
1232 Folder source = dao.getEntityById(Folder.class, folderId);
1233 Folder destination = dao.getEntityById(Folder.class, destId);
1234 User user = dao.getEntityById(User.class, userId);
1235 User sourceOwner = source.getOwner();
1236 User destinationOwner = destination.getOwner();
1237 // Do not move trashed folders and contents.
1238 if (source.isDeleted())
1240 // Check permissions.
1241 if (!destination.hasWritePermission(user)
1242 || !source.hasReadPermission(user)
1243 || !source.hasWritePermission(user))
1244 throw new InsufficientPermissionsException("You don't have the " +
1245 "necessary permissions");
1246 // Use the same timestamp for all subsequent modifications to make
1247 // changes appear simultaneous.
1248 Date now = new Date();
1249 // If source and destination are not in the same user's namespace,
1250 // change owners and check quota.
1251 if (!sourceOwner.equals(destinationOwner)) {
1252 changeOwner(source, destinationOwner, user, now);
1253 if (getQuotaLeft(destinationOwner.getId()) < 0)
1254 throw new QuotaExceededException("Not enough free space " +
1255 "available in destination folder");
1257 // Perform the move.
1258 Folder oldParent = source.getParent();
1259 oldParent.removeSubfolder(source);
1260 destination.addSubfolder(source);
1261 // Mark the former parent and destination trees upwards as modified.
1262 touchParentFolders(oldParent, user, now);
1263 touchParentFolders(source, user, now);
1267 * Recursively change the owner of the specified folder and all of its
1268 * contents to the specified owner. Also mark them all as modified with the
1269 * specified modifier and modificationDate.
1271 private void changeOwner(Folder folder, User owner, User modifier, Date modificationDate) {
1272 for (FileHeader file: folder.getFiles()) {
1273 file.setOwner(owner);
1274 file.getAuditInfo().setModificationDate(modificationDate);
1275 file.getAuditInfo().setModifiedBy(modifier);
1277 for (Folder sub: folder.getSubfolders())
1278 changeOwner(sub, owner, modifier, modificationDate);
1279 folder.setOwner(owner);
1280 folder.getAuditInfo().setModificationDate(modificationDate);
1281 folder.getAuditInfo().setModifiedBy(modifier);
1285 public List<FileHeaderDTO> getDeletedFiles(Long userId) throws ObjectNotFoundException {
1288 throw new ObjectNotFoundException("No user specified");
1290 // Do the actual work.
1291 final List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1292 final List<FileHeader> files = dao.getDeletedFiles(userId);
1293 for (final FileHeader f : files)
1294 result.add(f.getDTO());
1299 public void removeFileFromTrash(Long userId, Long fileId)
1300 throws ObjectNotFoundException, InsufficientPermissionsException {
1302 throw new ObjectNotFoundException("No user specified");
1304 throw new ObjectNotFoundException("No file specified");
1306 // Do the actual work.
1307 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1308 Folder parent = file.getFolder();
1310 throw new ObjectNotFoundException("The specified file has no parent folder");
1311 User user = dao.getEntityById(User.class, userId);
1312 if (!file.hasDeletePermission(user))
1313 throw new InsufficientPermissionsException("User " + user.getUsername() +
1314 " cannot restore file " + file.getName());
1316 file.setDeleted(false);
1318 touchParentFolders(parent, user, new Date());
1322 public void moveFolderToTrash(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 Folder folder = dao.getEntityById(Folder.class, folderId);
1328 User user = dao.getEntityById(User.class, userId);
1329 if (!folder.hasDeletePermission(user))
1330 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1331 folder.setDeleted(true);
1333 touchParentFolders(folder, user, new Date());
1334 for (FileHeader file : folder.getFiles())
1335 moveFileToTrash(userId, file.getId());
1336 for (Folder subFolder : folder.getSubfolders())
1337 moveFolderToTrash(userId, subFolder.getId());
1342 public void removeFolderFromTrash(Long userId, Long folderId)
1343 throws ObjectNotFoundException, InsufficientPermissionsException {
1345 throw new ObjectNotFoundException("No user specified");
1346 if (folderId == null)
1347 throw new ObjectNotFoundException("No folder specified");
1348 Folder folder = dao.getEntityById(Folder.class, folderId);
1349 User user = dao.getEntityById(User.class, userId);
1350 if (!folder.hasDeletePermission(user))
1351 throw new InsufficientPermissionsException("User " + user.getUsername() +
1352 " cannot restore folder " + folder.getName());
1353 folder.setDeleted(false);
1354 for (FileHeader file : folder.getFiles())
1355 removeFileFromTrash(userId, file.getId());
1356 for (Folder subFolder : folder.getSubfolders())
1357 removeFolderFromTrash(userId, subFolder.getId());
1359 touchParentFolders(folder, user, new Date());
1363 public List<FolderDTO> getDeletedRootFolders(Long userId) throws ObjectNotFoundException {
1364 List<Folder> folders = dao.getDeletedRootFolders(userId);
1365 List<FolderDTO> result = new ArrayList<FolderDTO>();
1366 for (Folder folder : folders)
1367 result.add(folder.getDTO());
1372 public void emptyTrash(Long userId) throws ObjectNotFoundException, InsufficientPermissionsException {
1373 List<FolderDTO> deletedRootFolders = getDeletedRootFolders(userId);
1374 for (FolderDTO fdto : deletedRootFolders)
1375 deleteFolder(userId, fdto.getId());
1376 List<FileHeaderDTO> deletedFiles = getDeletedFiles(userId);
1377 for (FileHeaderDTO filedto : deletedFiles)
1378 deleteFile(userId, filedto.getId());
1382 public void restoreTrash(Long userId) throws ObjectNotFoundException, InsufficientPermissionsException {
1383 List<FolderDTO> deletedRootFolders = getDeletedRootFolders(userId);
1384 for (FolderDTO fdto : deletedRootFolders)
1385 removeFolderFromTrash(userId, fdto.getId());
1386 List<FileHeaderDTO> deletedFiles = getDeletedFiles(userId);
1387 for (FileHeaderDTO filedto : deletedFiles)
1388 removeFileFromTrash(userId, filedto.getId());
1392 public User createUser(String username, String name, String mail,
1393 String idp, String idpid) throws ObjectNotFoundException {
1394 if (username == null)
1395 throw new ObjectNotFoundException("No username specified");
1397 throw new ObjectNotFoundException("No name specified");
1399 User user = new User();
1400 user.setUsername(username);
1402 user.setEmail(mail);
1403 user.setIdentityProvider(idp);
1404 user.setIdentityProviderId(idpid);
1405 Date now = new Date();
1406 AuditInfo auditInfo = new AuditInfo();
1407 auditInfo.setCreationDate(now);
1408 auditInfo.setModificationDate(now);
1409 user.setAuditInfo(auditInfo);
1410 user.setActive(true);
1411 user.generateAuthToken();
1412 user.generateWebDAVPassword();
1413 user.setUserClass(getDefaultUserClass());
1415 // Make sure we get an ID in the user object.
1417 // Create the root folder for the user.
1418 createFolder(user.getName(), null, user);
1423 * Get the default user class, which is the one with the lowest quota.
1425 private UserClass getDefaultUserClass() {
1426 return getUserClasses().get(0);
1430 public List<UserClass> getUserClasses() {
1431 List<UserClass> classes = dao.getUserClasses();
1432 // Create a default user class for first-time use. Afterwards, the
1433 // admin should modify or add to the userclass table.
1434 if (classes.size() == 0) {
1435 UserClass defaultClass = new UserClass();
1436 defaultClass.setName("default");
1437 Long defaultQuota = getConfiguration().getLong("quota", new Long(52428800L));
1438 defaultClass.setQuota(defaultQuota);
1439 dao.create(defaultClass);
1440 classes.add(defaultClass);
1446 public User findUserByEmail(String email) {
1447 return dao.findUserByEmail(email);
1451 public void updateUser(User user) {
1456 public User findUser(String username) {
1457 if (username == null)
1459 return dao.findUser(username);
1463 public User updateUserToken(Long userId) throws ObjectNotFoundException {
1465 throw new ObjectNotFoundException("No user specified");
1466 User user = dao.getEntityById(User.class, userId);
1467 user.generateAuthToken();
1472 public Set<PermissionDTO> getFolderPermissions(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
1474 throw new ObjectNotFoundException("No user specified");
1475 if (folderId == null)
1476 throw new ObjectNotFoundException("No folder specified");
1477 User user = dao.getEntityById(User.class, userId);
1478 Folder folder = dao.getEntityById(Folder.class, folderId);
1479 if(!folder.hasReadPermission(user))
1480 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1481 Set<Permission> perms = folder.getPermissions();
1482 Set<PermissionDTO> result = new LinkedHashSet<PermissionDTO>();
1483 for (Permission perm : perms)
1484 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId()))
1485 result.add(perm.getDTO());
1486 for (Permission perm : perms)
1487 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId())) {
1489 result.add(perm.getDTO());
1495 * Set the provided permissions as the new permissions of the specified
1500 * @param permissions
1501 * @throws ObjectNotFoundException
1502 * @throws InsufficientPermissionsException
1504 private void setFolderPermissions(User user, Folder folder, Set<PermissionDTO> permissions) throws ObjectNotFoundException, InsufficientPermissionsException {
1505 if (permissions != null && !permissions.isEmpty()) {
1506 User owner = folder.getOwner();
1507 PermissionDTO ownerPerm = null;
1508 for (PermissionDTO dto : permissions)
1509 if (dto.getUser() != null && dto.getUser().getId().equals(owner.getId())) {
1513 if (ownerPerm == null || !ownerPerm.hasRead() || !ownerPerm.hasWrite() || !ownerPerm.hasModifyACL())
1514 throw new InsufficientPermissionsException("Can't remove permissions from owner");
1515 // Delete previous entries
1516 for (Permission perm: folder.getPermissions())
1518 folder.getPermissions().clear();
1519 for (PermissionDTO dto : permissions) {
1520 // Skip 'empty' permission entries.
1521 if (!dto.getRead() && !dto.getWrite() && !dto.getModifyACL()) continue;
1522 folder.addPermission(getPermission(dto));
1525 for (FileHeader file : folder.getFiles()) {
1526 setFilePermissions(file, permissions);
1527 Date now = new Date();
1528 file.getAuditInfo().setModificationDate(now);
1529 file.getAuditInfo().setModifiedBy(user);
1531 for (Folder sub : folder.getSubfolders())
1532 setFolderPermissions(user, sub, permissions);
1536 private Permission getPermission(PermissionDTO dto) throws ObjectNotFoundException {
1537 Permission res = new Permission();
1538 if (dto.getGroup() != null)
1539 res.setGroup(dao.getEntityById(Group.class, dto.getGroup().getId()));
1540 else if (dto.getUser() != null)
1541 if (dto.getUser().getId() == null)
1542 res.setUser(dao.getUser(dto.getUser().getUsername()));
1544 res.setUser(dao.getEntityById(User.class, dto.getUser().getId()));
1545 res.setRead(dto.hasRead());
1546 res.setWrite(dto.hasWrite());
1547 res.setModifyACL(dto.hasModifyACL());
1552 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsersByUserNameLike(java.lang.String)
1555 public List<UserDTO> getUsersByUserNameLike(String username) {
1556 List<User> users = dao.getUsersByUserNameLike(username);
1557 List<UserDTO> result = new ArrayList<UserDTO>();
1558 for (User u : users)
1559 result.add(u.getDTO());
1565 public void addUserToGroup(Long userId, Long groupId, Long userToAddId) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
1567 throw new ObjectNotFoundException("No user specified");
1568 if (groupId == null)
1569 throw new ObjectNotFoundException("No group specified");
1570 if (userToAddId == null)
1571 throw new ObjectNotFoundException("No user to add specified");
1572 User user = dao.getEntityById(User.class, userId);
1573 Group group = dao.getEntityById(Group.class, groupId);
1574 if (!group.getOwner().equals(user))
1575 throw new InsufficientPermissionsException();
1576 User userToAdd = dao.getEntityById(User.class, userToAddId);
1577 if (group.contains(userToAdd))
1578 throw new DuplicateNameException("User already exists in group");
1579 group.getMembers().add(userToAdd);
1585 public void invalidateUserToken(Long userId) throws ObjectNotFoundException {
1587 throw new ObjectNotFoundException("No user specified");
1588 User user = dao.getEntityById(User.class, userId);
1589 user.invalidateAuthToken();
1594 public List<FolderDTO> getSharedRootFolders(Long userId) throws ObjectNotFoundException {
1596 throw new ObjectNotFoundException("No user specified");
1597 List<Folder> folders = dao.getSharedRootFolders(userId);
1598 List<FolderDTO> result = new ArrayList<FolderDTO>();
1599 for (Folder f : folders) {
1600 FolderDTO dto = f.getDTO();
1601 dto.setSubfolders(getSharedSubfolders(userId, f.getId()));
1608 public void removeMemberFromGroup(Long userId, Long groupId, Long memberId) throws ObjectNotFoundException, InsufficientPermissionsException {
1610 throw new ObjectNotFoundException("No user specified");
1611 if (groupId == null)
1612 throw new ObjectNotFoundException("No group specified");
1613 if (memberId == null)
1614 throw new ObjectNotFoundException("No member specified");
1615 User owner = dao.getEntityById(User.class, userId);
1616 Group group = dao.getEntityById(Group.class, groupId);
1617 User member = dao.getEntityById(User.class, memberId);
1618 if (!group.getOwner().equals(owner))
1619 throw new InsufficientPermissionsException("User is not the owner of the group");
1620 group.removeMemberFromGroup(member);
1626 public List<UserDTO> getUsersSharingFoldersForUser(Long userId) throws ObjectNotFoundException {
1627 List<User> users = dao.getUsersSharingFoldersForUser(userId);
1628 List<User> usersFiles = dao.getUsersSharingFilesForUser(userId);
1629 List<UserDTO> res = new ArrayList<UserDTO>();
1630 for (User u : users)
1631 res.add(u.getDTO());
1632 for(User fu : usersFiles)
1633 if(!users.contains(fu))
1634 res.add(fu.getDTO());
1639 public Set<PermissionDTO> getFilePermissions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1641 throw new ObjectNotFoundException("No user specified");
1643 throw new ObjectNotFoundException("No folder specified");
1644 User user = dao.getEntityById(User.class, userId);
1645 FileHeader folder = dao.getEntityById(FileHeader.class, fileId);
1646 if(!folder.hasReadPermission(user))
1647 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1648 Set<Permission> perms = folder.getPermissions();
1649 Set<PermissionDTO> result = new LinkedHashSet<PermissionDTO>();
1650 for (Permission perm : perms)
1651 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId()))
1652 result.add(perm.getDTO());
1653 for (Permission perm : perms)
1654 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId())) {
1656 result.add(perm.getDTO());
1661 * Set the provided permissions as the new permissions of the specified
1662 * file. This method sets the modification date/user attributes to the
1663 * current values as a side effect.
1666 * @param permissions
1667 * @throws ObjectNotFoundException
1668 * @throws InsufficientPermissionsException
1670 private void setFilePermissions(FileHeader file,
1671 Set<PermissionDTO> permissions)
1672 throws ObjectNotFoundException, InsufficientPermissionsException {
1673 if (permissions != null && !permissions.isEmpty()) {
1674 PermissionDTO ownerPerm = null;
1675 for (PermissionDTO dto : permissions)
1676 if (dto.getUser() != null && dto.getUser().getId().equals(file.getOwner().getId())) {
1680 if (ownerPerm == null || !ownerPerm.hasRead() || !ownerPerm.hasWrite() || !ownerPerm.hasModifyACL())
1681 throw new InsufficientPermissionsException("Can't remove permissions from owner");
1682 // Delete previous entries.
1683 for (Permission perm: file.getPermissions())
1685 file.getPermissions().clear();
1686 for (PermissionDTO dto : permissions) {
1687 // Skip 'empty' permission entries.
1688 if (!dto.getRead() && !dto.getWrite() && !dto.getModifyACL()) continue;
1689 file.addPermission(getPermission(dto));
1696 public List<FileHeaderDTO> getSharedFilesNotInSharedFolders(Long userId) throws ObjectNotFoundException {
1698 throw new ObjectNotFoundException("No user specified");
1699 List<FileHeader> files = dao.getSharedFilesNotInSharedFolders(userId);
1700 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1701 for (FileHeader f : files)
1702 result.add(f.getDTO());
1707 public List<FileHeaderDTO> getSharedFiles(Long userId) throws ObjectNotFoundException {
1709 throw new ObjectNotFoundException("No user specified");
1710 List<FileHeader> files = dao.getSharedFiles(userId);
1711 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1712 for (FileHeader f : files)
1713 result.add(f.getDTO());
1718 public List<FolderDTO> getSharedFolders(Long userId) throws ObjectNotFoundException {
1720 throw new ObjectNotFoundException("No user specified");
1721 List<Folder> folders = dao.getSharedFolders(userId);
1722 List<FolderDTO> result = new ArrayList<FolderDTO>();
1723 for (Folder f : folders)
1724 result.add(f.getDTO());
1729 public List<FileHeaderDTO> getSharedFiles(Long ownerId, Long callingUserId) throws ObjectNotFoundException {
1730 if (ownerId == null)
1731 throw new ObjectNotFoundException("No owner specified");
1732 if (callingUserId == null)
1733 throw new ObjectNotFoundException("No calling user specified");
1734 List<FileHeader> folders = dao.getSharedFiles(ownerId, callingUserId);
1735 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1736 for (FileHeader f : folders)
1737 result.add(f.getDTO());
1742 public List<FolderDTO> getSharedRootFolders(Long ownerId, Long callingUserId) throws ObjectNotFoundException {
1743 if (ownerId == null)
1744 throw new ObjectNotFoundException("No owner specified");
1745 if (callingUserId == null)
1746 throw new ObjectNotFoundException("No calling user specified");
1747 List<Folder> folders = dao.getSharedRootFolders(ownerId, callingUserId);
1748 List<FolderDTO> result = new ArrayList<FolderDTO>();
1749 for (Folder f : folders) {
1750 FolderDTO dto = f.getDTO();
1751 dto.setSubfolders(getSharedSubfolders(ownerId, callingUserId, f.getId()));
1759 public List<FolderDTO> getSharedSubfolders(Long userId, Long folderId) throws ObjectNotFoundException {
1761 throw new ObjectNotFoundException("No user specified");
1762 if (folderId == null)
1763 throw new ObjectNotFoundException("No folder specified");
1764 User user = dao.getEntityById(User.class, userId);
1765 Folder folder = dao.getEntityById(Folder.class, folderId);
1766 List<FolderDTO> result = new ArrayList<FolderDTO>();
1767 if (folder.isShared(user) || folder.isReadForAll())
1768 for (Folder f : folder.getSubfolders())
1769 if ((f.isShared(user) || f.isReadForAll()) && !f.isDeleted())
1770 result.add(f.getDTO());
1775 public List<FolderDTO> getSharedSubfolders(Long userId, Long callingUserId, Long folderId) throws ObjectNotFoundException {
1777 throw new ObjectNotFoundException("No user specified");
1778 if (callingUserId == null)
1779 throw new ObjectNotFoundException("No user specified");
1780 if (folderId == null)
1781 throw new ObjectNotFoundException("No folder specified");
1782 User user = dao.getEntityById(User.class, callingUserId);
1783 Folder folder = dao.getEntityById(Folder.class, folderId);
1784 List<FolderDTO> result = new ArrayList<FolderDTO>();
1785 if (folder.isSharedForOtherUser(user))
1786 for (Folder f : folder.getSubfolders())
1787 if (f.isSharedForOtherUser(user) && !f.isDeleted()){
1788 FolderDTO dto = f.getDTO();
1789 dto.setSubfolders(getSharedSubfolders(userId, callingUserId, dto.getId()));
1797 public List<FileHeader> searchFiles(Long userId, String query) throws ObjectNotFoundException {
1798 long startTime = System.currentTimeMillis();
1800 throw new ObjectNotFoundException("No user specified");
1801 User user = getUser(userId);
1803 throw new ObjectNotFoundException("No query specified");
1804 List<FileHeader> files = search(user.getId(), query);
1806 long stopTime = System.currentTimeMillis();
1807 logger.info("Total time: " + (stopTime - startTime));
1812 * Performs the actuals search on the solr server and returns the results
1816 * @return a List of FileHeader objects
1818 private List<FileHeader> search(Long userId, String query) {
1819 final int maxRows = 100;
1820 List<FileHeader> result = new ArrayList<FileHeader>();
1822 CommonsHttpSolrServer solr = new CommonsHttpSolrServer(getConfiguration().getString("solr.url"));
1823 List<Group> groups = dao.getGroupsContainingUser(userId);
1824 String constructedQuery = escapeCharacters(normalizeSearchQuery(query)) + " AND (public: true OR ureaders: " + userId;
1825 if (!groups.isEmpty()) {
1826 constructedQuery += " OR (";
1827 for (int i=0; i<groups.size(); i++) {
1828 Group g = groups.get(i);
1829 constructedQuery += "greaders :" + g.getId();
1830 if (i < groups.size() - 1)
1831 constructedQuery += " OR ";
1833 constructedQuery += ")";
1835 constructedQuery += ")";
1836 SolrQuery solrQuery = new SolrQuery(constructedQuery);
1837 solrQuery.setRows(maxRows);
1838 long startTime = System.currentTimeMillis();
1839 QueryResponse response = solr.query(solrQuery);
1840 SolrDocumentList results = response.getResults();
1841 if (results.getNumFound() > maxRows) {
1842 solrQuery.setRows(Integer.valueOf((int) results.getNumFound()));
1843 response = solr.query(solrQuery);
1844 results = response.getResults();
1846 long stopTime = System.currentTimeMillis();
1847 logger.info("Search time:" + (stopTime - startTime));
1848 User user = getUser(userId);
1849 startTime = System.currentTimeMillis();
1850 for (SolrDocument d : results) {
1851 Long id = Long.valueOf((String) d.getFieldValue("id"));
1853 FileHeader f = dao.getEntityById(FileHeader.class, id);
1855 } catch (ObjectNotFoundException e) {
1856 logger.warn("Search result id " + id + " cannot be found", e);
1859 stopTime = System.currentTimeMillis();
1860 logger.info("File loads: " + (stopTime - startTime));
1861 } catch (MalformedURLException e) {
1863 throw new EJBException(e);
1864 } catch (SolrServerException e) {
1866 throw new EJBException(e);
1867 } catch (ObjectNotFoundException e) {
1869 throw new EJBException(e);
1875 public void copyFiles(Long userId, List<Long> fileIds, Long destId) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
1876 for(Long l : fileIds){
1877 FileHeader file = dao.getEntityById(FileHeader.class, l);
1878 copyFile(userId, l, destId, file.getName());
1885 public void moveFiles(Long userId, List<Long> fileIds, Long destId) throws InsufficientPermissionsException, ObjectNotFoundException, QuotaExceededException {
1886 for(Long l : fileIds){
1887 FileHeader file = dao.getEntityById(FileHeader.class, l);
1888 moveFile(userId, l, destId, file.getName());
1894 public void deleteFiles(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1896 throw new ObjectNotFoundException("No user specified");
1897 final User user = dao.getEntityById(User.class, userId);
1898 List<String> filesToRemove = new ArrayList<String>();
1899 //first delete database objects
1900 for(Long fileId : fileIds){
1902 throw new ObjectNotFoundException("No file specified");
1903 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1904 final Folder parent = file.getFolder();
1906 throw new ObjectNotFoundException("The specified file has no parent folder");
1907 if (!file.hasDeletePermission(user))
1908 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
1910 parent.removeFile(file);
1911 for (final FileBody body : file.getBodies())
1912 filesToRemove.add(body.getStoredFilePath());
1914 touchParentFolders(parent, user, new Date());
1916 //then remove physical files if everything is ok
1917 for(String physicalFileName : filesToRemove)
1918 deleteActualFile(physicalFileName);
1919 //then unindex deleted files
1920 for(Long fileId : fileIds)
1921 indexFile(fileId, true);
1926 public void moveFilesToTrash(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1927 for(Long l : fileIds)
1928 moveFileToTrash(userId, l);
1933 public void removeFilesFromTrash(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1934 for(Long l : fileIds)
1935 removeFileFromTrash(userId, l);
1940 public Nonce createNonce(Long userId) throws ObjectNotFoundException {
1942 throw new ObjectNotFoundException("No user specified");
1943 User user = dao.getEntityById(User.class, userId);
1944 Nonce nonce = Nonce.createNonce(user.getId());
1950 public Nonce getNonce(String nonce, Long userId) throws ObjectNotFoundException {
1952 throw new ObjectNotFoundException("No user specified");
1954 throw new ObjectNotFoundException("No nonce specified");
1955 return dao.getNonce(nonce, userId);
1959 public void removeNonce(Long id) throws ObjectNotFoundException {
1961 throw new ObjectNotFoundException("No nonce specified");
1962 Nonce nonce = dao.getEntityById(Nonce.class, id);
1967 public void activateUserNonce(Long userId, String nonce, Date nonceExpiryDate) throws ObjectNotFoundException {
1969 throw new ObjectNotFoundException("No user specified");
1970 User user = dao.getEntityById(User.class, userId);
1971 user.setNonce(nonce);
1972 user.setNonceExpiryDate(nonceExpiryDate);
1976 public StatsDTO getUserStatistics(Long userId) throws ObjectNotFoundException {
1978 throw new ObjectNotFoundException("No user specified");
1979 StatsDTO stats = new StatsDTO();
1980 stats.setFileCount(dao.getFileCount(userId));
1981 Long fileSize = dao.getFileSize(userId);
1982 stats.setFileSize(fileSize);
1983 Long quota = getQuota(userId);
1984 Long quotaLeft = quota - fileSize;
1985 stats.setQuotaLeftSize(quotaLeft);
1990 public List<FileBodyDTO> getVersions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1992 throw new ObjectNotFoundException("No user specified");
1994 throw new ObjectNotFoundException("No file specified");
1995 User user = dao.getEntityById(User.class, userId);
1996 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
1997 if(!header.hasReadPermission(user))
1998 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1999 List<FileBodyDTO> result = new LinkedList<FileBodyDTO>();
2000 for(int i = header.getBodies().size()-1 ; i>=0; i--)
2001 result.add(header.getBodies().get(i).getDTO());
2006 public void removeVersion(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
2008 throw new ObjectNotFoundException("No user specified");
2010 throw new ObjectNotFoundException("No file specified");
2012 throw new ObjectNotFoundException("No body specified");
2013 User user = dao.getEntityById(User.class, userId);
2014 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
2015 if(!header.hasWritePermission(user))
2016 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2017 FileBody body = dao.getEntityById(FileBody.class, bodyId);
2018 if(body.equals(header.getCurrentBody())){
2020 if(header.getBodies().size() == 1)
2021 throw new InsufficientPermissionsException("You cant delete this version, Delete file instead!");
2022 for(FileBody b : header.getBodies())
2023 if(b.getVersion() == body.getVersion()-1)
2024 header.setCurrentBody(b);
2026 deleteActualFile(body.getStoredFilePath());
2027 header.getBodies().remove(body);
2029 Folder parent = header.getFolder();
2030 touchParentFolders(parent, user, new Date());
2035 public void restoreVersion(Long userId, Long fileId, int version) throws ObjectNotFoundException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
2037 throw new ObjectNotFoundException("No user specified");
2039 throw new ObjectNotFoundException("No file specified");
2040 User user = dao.getEntityById(User.class, userId);
2041 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
2042 if(!header.hasWritePermission(user))
2043 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2044 FileBody body = dao.getFileVersion(fileId, version);
2045 final File fileContents = new File(body.getStoredFilePath());
2048 updateFileContents(userId, fileId, body.getMimeType(), new FileInputStream(fileContents) );
2049 } catch (FileNotFoundException e) {
2050 throw new GSSIOException(e);
2056 * @see gr.ebs.gss.server.ejb.ExternalAPI#removeOldVersions(java.lang.Long, java.lang.Long)
2059 public void removeOldVersions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
2061 throw new ObjectNotFoundException("No user specified");
2063 throw new ObjectNotFoundException("No file specified");
2064 User user = dao.getEntityById(User.class, userId);
2065 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
2066 if(!header.hasWritePermission(user))
2067 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2068 Iterator<FileBody> it = header.getBodies().iterator();
2069 while(it.hasNext()){
2070 FileBody body = it.next();
2071 if(!body.equals(header.getCurrentBody())){
2072 deleteActualFile(body.getStoredFilePath());
2077 header.getCurrentBody().setVersion(1);
2079 Folder parent = header.getFolder();
2080 touchParentFolders(parent, user, new Date());
2084 * Gets the quota left for specified user ID.
2086 private Long getQuotaLeft(Long userId) throws ObjectNotFoundException{
2087 Long fileSize = dao.getFileSize(userId);
2088 Long quota = getQuota(userId);
2089 return quota - fileSize;
2093 * Gets the quota for specified user ID.
2095 private Long getQuota(Long userId) throws ObjectNotFoundException{
2096 UserClass uc = getUser(userId).getUserClass();
2098 uc = getDefaultUserClass();
2099 return uc.getQuota();
2103 @TransactionAttribute(TransactionAttributeType.NEVER)
2104 public String rebuildSolrIndex() {
2106 CommonsHttpSolrServer solr = new CommonsHttpSolrServer(getConfiguration().getString("solr.url"));
2107 solr.deleteByQuery("*:*");
2109 logger.info("Deleted everything in solr");
2111 List<Long> fileIds = dao.getAllFileIds();
2112 logger.info("Total of " + fileIds.size() + " will be indexed");
2114 for (Long id : fileIds) {
2115 postFileToSolr(solr, id);
2119 logger.info("Sent commit to solr at file " + i);
2124 logger.info("Finished indexing of " + i + " files");
2125 return "Finished indexing of " + i + " files";
2126 } catch (IOException e) {
2127 throw new EJBException(e);
2128 } catch (SolrServerException e) {
2129 throw new EJBException(e);
2134 @TransactionAttribute(TransactionAttributeType.NEVER)
2135 public String refreshSolrIndex() {
2137 CommonsHttpSolrServer solr = new CommonsHttpSolrServer(getConfiguration().getString("solr.url"));
2139 List<Long> fileIds = dao.getAllFileIds();
2140 logger.info("Total of " + fileIds.size() + " will be indexed");
2142 for (Long id : fileIds) {
2143 postFileToSolr(solr, id);
2148 logger.info("Sent commit to solr at file " + i);
2152 logger.info("Finished indexing of " + i + " files");
2153 return "Finished indexing of " + i + " files";
2154 } catch (IOException e) {
2155 throw new EJBException(e);
2156 } catch (SolrServerException e) {
2157 throw new EJBException(e);
2162 public FileHeaderDTO createFile(Long userId, Long folderId, String name, String mimeType, long fileSize, String filePath)
2163 throws DuplicateNameException, ObjectNotFoundException, GSSIOException,
2164 InsufficientPermissionsException, QuotaExceededException {
2167 throw new ObjectNotFoundException("No user specified");
2168 if (folderId == null)
2169 throw new ObjectNotFoundException("No folder specified");
2170 String contentType = mimeType;
2171 if (StringUtils.isEmpty(mimeType))
2172 contentType = DEFAULT_MIME_TYPE;
2173 if (StringUtils.isEmpty(name))
2174 throw new ObjectNotFoundException("No file name specified");
2175 if (dao.existsFolderOrFile(folderId, name))
2176 throw new DuplicateNameException("A folder or file with the name '" + name +
2177 "' already exists at this level");
2179 // Do the actual work.
2180 Folder parent = null;
2182 parent = dao.getEntityById(Folder.class, folderId);
2183 } catch (final ObjectNotFoundException onfe) {
2184 // Supply a more accurate problem description.
2185 throw new ObjectNotFoundException("Parent folder not found");
2187 final User owner = dao.getEntityById(User.class, userId);
2188 if (!parent.hasWritePermission(owner))
2189 throw new InsufficientPermissionsException("You don't have the permissions to write to this folder");
2190 final FileHeader file = new FileHeader();
2192 parent.addFile(file);
2193 // set file owner to folder owner
2194 file.setOwner(parent.getOwner());
2195 //set file's readForAll value according to parent folder readForAll value
2196 file.setReadForAll(parent.isReadForAll());
2198 final Date now = new Date();
2199 final AuditInfo auditInfo = new AuditInfo();
2200 auditInfo.setCreatedBy(owner);
2201 auditInfo.setCreationDate(now);
2202 auditInfo.setModifiedBy(owner);
2203 auditInfo.setModificationDate(now);
2204 file.setAuditInfo(auditInfo);
2205 // TODO set the proper versioning flag on creation
2206 file.setVersioned(false);
2208 for (final Permission p : parent.getPermissions()) {
2209 final Permission permission = new Permission();
2210 permission.setGroup(p.getGroup());
2211 permission.setUser(p.getUser());
2212 permission.setRead(p.getRead());
2213 permission.setWrite(p.getWrite());
2214 permission.setModifyACL(p.getModifyACL());
2215 file.addPermission(permission);
2218 // Create the file body.
2220 createFileBody(name, contentType, fileSize, filePath, file, auditInfo);
2221 } catch (FileNotFoundException e) {
2222 throw new GSSIOException(e);
2224 touchParentFolders(parent, owner, new Date());
2226 indexFile(file.getId(), false);
2228 return file.getDTO();
2232 public FileHeaderDTO updateFileContents(Long userId, Long fileId, String mimeType, long fileSize, String filePath) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
2234 throw new ObjectNotFoundException("No user specified");
2236 throw new ObjectNotFoundException("No file specified");
2237 String contentType = mimeType;
2239 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
2241 // if no mime type or the generic mime type is defined by the client, then try to identify it from the filename extension
2242 if (StringUtils.isEmpty(mimeType) || "application/octet-stream".equals(mimeType)
2243 || "application/download".equals(mimeType) || "application/force-download".equals(mimeType)
2244 || "octet/stream".equals(mimeType) || "application/unknown".equals(mimeType))
2245 contentType = identifyMimeType(file.getName());
2247 final User owner = dao.getEntityById(User.class, userId);
2248 if (!file.hasWritePermission(owner))
2249 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2250 final Date now = new Date();
2251 final AuditInfo auditInfo = new AuditInfo();
2252 auditInfo.setCreatedBy(owner);
2253 auditInfo.setCreationDate(now);
2254 auditInfo.setModifiedBy(owner);
2255 auditInfo.setModificationDate(now);
2257 createFileBody(file.getName(), contentType, fileSize, filePath, file, auditInfo);
2258 } catch (FileNotFoundException e) {
2259 throw new GSSIOException(e);
2261 Folder parent = file.getFolder();
2262 touchParentFolders(parent, owner, new Date());
2264 indexFile(fileId, false);
2265 return file.getDTO();
2269 * Helper method for identifying mime type by examining the filename extension
2272 * @return the mime type
2274 private String identifyMimeType(String filename) {
2275 if (filename.indexOf('.') != -1) {
2276 String extension = filename.substring(filename.lastIndexOf('.')).toLowerCase(Locale.ENGLISH);
2277 if (".doc".equals(extension))
2278 return "application/msword";
2279 else if (".xls".equals(extension))
2280 return "application/vnd.ms-excel";
2281 else if (".ppt".equals(extension))
2282 return "application/vnd.ms-powerpoint";
2283 else if (".pdf".equals(extension))
2284 return "application/pdf";
2285 else if (".gif".equals(extension))
2287 else if (".jpg".equals(extension) || ".jpeg".equals(extension) || ".jpe".equals(extension))
2288 return "image/jpeg";
2289 else if (".tiff".equals(extension) || ".tif".equals(extension))
2290 return "image/tiff";
2291 else if (".png".equals(extension))
2293 else if (".bmp".equals(extension))
2296 // when all else fails assign the default mime type
2297 return DEFAULT_MIME_TYPE;
2301 * Helper method to create a new file body and attach it as the current body
2302 * of the provided file header.
2304 * @param name the original file name
2305 * @param mimeType the content type
2306 * @param fileSize the uploaded file size
2307 * @param filePath the uploaded file full path
2308 * @param header the file header that will be associated with the new body
2309 * @param auditInfo the audit info
2310 * @throws FileNotFoundException
2311 * @throws QuotaExceededException
2312 * @throws ObjectNotFoundException if the owner was not found
2314 private void createFileBody(String name, String mimeType, long fileSize, String filePath,
2315 FileHeader header, AuditInfo auditInfo)
2316 throws FileNotFoundException, QuotaExceededException, ObjectNotFoundException {
2318 long currentTotalSize = 0;
2319 if (!header.isVersioned() && header.getCurrentBody() != null && header.getBodies() != null)
2320 currentTotalSize = header.getTotalSize();
2321 Long quotaLeft = getQuotaLeft(header.getOwner().getId());
2322 if(quotaLeft < fileSize-currentTotalSize) {
2323 // quota exceeded -> delete the file
2324 deleteActualFile(filePath);
2325 throw new QuotaExceededException("Not enough free space available");
2328 FileBody body = new FileBody();
2330 // if no mime type or the generic mime type is defined by the client, then try to identify it from the filename extension
2331 if (StringUtils.isEmpty(mimeType) || "application/octet-stream".equals(mimeType)
2332 || "application/download".equals(mimeType) || "application/force-download".equals(mimeType)
2333 || "octet/stream".equals(mimeType) || "application/unknown".equals(mimeType))
2334 body.setMimeType(identifyMimeType(name));
2336 body.setMimeType(mimeType);
2337 body.setAuditInfo(auditInfo);
2338 body.setFileSize(fileSize);
2339 body.setOriginalFilename(name);
2340 body.setStoredFilePath(filePath);
2341 //CLEAR OLD VERSION IF FILE IS NOT VERSIONED AND GETS UPDATED
2342 if(!header.isVersioned() && header.getCurrentBody() != null){
2343 header.setCurrentBody(null);
2344 if (header.getBodies() != null) {
2345 Iterator<FileBody> it = header.getBodies().iterator();
2346 while(it.hasNext()){
2347 FileBody bo = it.next();
2348 deleteActualFile(bo.getStoredFilePath());
2356 header.addBody(body);
2357 header.setAuditInfo(auditInfo);
2364 @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
2365 public File uploadFile(InputStream stream, Long userId) throws IOException, ObjectNotFoundException {
2367 throw new ObjectNotFoundException("No user specified");
2368 User owner = dao.getEntityById(User.class, userId);
2370 throw new ObjectNotFoundException("No user specified");
2371 long start = 0, end = 0;
2372 if (logger.isDebugEnabled())
2373 start = System.currentTimeMillis();
2374 File result = new File(generateRepositoryFilePath());
2376 final FileOutputStream output = new FileOutputStream(result);
2377 final byte[] buffer = new byte[UPLOAD_BUFFER_SIZE];
2380 while (-1 != (n = stream.read(buffer)))
2381 output.write(buffer, 0, n);
2384 } catch (IOException e) {
2385 if (!result.delete())
2386 logger.warn("Could not delete " + result.getPath());
2389 if (logger.isDebugEnabled()) {
2390 end = System.currentTimeMillis();
2391 logger.debug("Time to upload: " + (end - start) + " (msec)");
2398 public void createFileUploadProgress(Long userId, String filename, Long bytesTransfered, Long fileSize) throws ObjectNotFoundException{
2401 throw new ObjectNotFoundException("No user specified");
2402 User user = dao.getEntityById(User.class, userId);
2403 FileUploadStatus status = dao.getFileUploadStatus(userId, filename);
2405 status = new FileUploadStatus();
2406 status.setOwner(user);
2407 status.setFilename(filename);
2408 status.setBytesUploaded(bytesTransfered);
2409 status.setFileSize(fileSize);
2413 status.setBytesUploaded(bytesTransfered);
2414 status.setFileSize(fileSize);
2421 public void removeFileUploadProgress(Long userId, String filename) throws ObjectNotFoundException{
2423 throw new ObjectNotFoundException("No user specified");
2424 FileUploadStatus status = dao.getFileUploadStatus(userId, filename);
2430 public FileUploadStatus getFileUploadStatus(Long userId, String fileName) {
2431 return dao.getFileUploadStatus(userId, fileName);
2435 public FolderDTO getFolderWithSubfolders(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
2437 throw new ObjectNotFoundException("No user specified");
2438 if (folderId == null)
2439 throw new ObjectNotFoundException("No folder specified");
2440 final User user = dao.getEntityById(User.class, userId);
2441 final Folder folder = dao.getEntityById(Folder.class, folderId);
2442 // Check permissions
2443 if (!folder.hasReadPermission(user))
2444 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
2445 List<FolderDTO> subfolders = new ArrayList<FolderDTO>();
2446 if (folder.hasReadPermission(user))
2447 for (Folder f : folder.getSubfolders())
2448 if (f.hasReadPermission(user) && !f.isDeleted())
2449 subfolders.add(f.getDTO());
2450 FolderDTO result = folder.getDTO();
2451 result.setSubfolders(subfolders);
2452 return folder.getDTO();
2456 public FolderDTO getFolderWithSubfolders(Long userId, Long callingUserId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
2458 throw new ObjectNotFoundException("No user specified");
2459 if (folderId == null)
2460 throw new ObjectNotFoundException("No folder specified");
2461 User user = dao.getEntityById(User.class, callingUserId);
2462 Folder folder = dao.getEntityById(Folder.class, folderId);
2463 // Check permissions
2464 if (!folder.hasReadPermission(user))
2465 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
2467 FolderDTO result = folder.getDTO();
2468 result.setSubfolders(getSharedSubfolders(userId, callingUserId, folder.getId()));
2473 public FileBodyDTO getFileVersion(Long userId, Long fileId, int version)
2474 throws ObjectNotFoundException, InsufficientPermissionsException {
2476 throw new ObjectNotFoundException("No user specified");
2478 throw new ObjectNotFoundException("No file specified");
2480 throw new ObjectNotFoundException("No valid version specified");
2481 User user = dao.getEntityById(User.class, userId);
2482 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
2483 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
2484 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2485 FileBody body = dao.getFileVersion(fileId, version);
2486 return body.getDTO();
2490 public User updateUserPolicyAcceptance(Long userId, boolean isAccepted) throws ObjectNotFoundException {
2492 throw new ObjectNotFoundException("No user specified");
2493 User user = dao.getEntityById(User.class, userId);
2494 user.setAcceptedPolicy(isAccepted);
2499 public void updateAccounting(User user, Date date, long bandwidthDiff) {
2500 dao.updateAccounting(user, date, bandwidthDiff);
2504 public boolean canReadFolder(Long userId, Long folderId) throws ObjectNotFoundException {
2506 throw new ObjectNotFoundException("No user specified");
2507 if (folderId == null)
2508 throw new ObjectNotFoundException("No folder specified");
2509 User user = dao.getEntityById(User.class, userId);
2510 Folder folder = dao.getEntityById(Folder.class, folderId);
2511 // Check permissions
2512 if (!folder.hasReadPermission(user))
2518 public String resetWebDAVPassword(Long userId) throws ObjectNotFoundException {
2520 throw new ObjectNotFoundException("No user specified");
2521 User user = dao.getEntityById(User.class, userId);
2522 user.generateWebDAVPassword();
2523 return user.getWebDAVPassword();
2527 public Invitation findInvite(String code) {
2530 return dao.findInvite(code);
2534 public void createLdapUser(String username, String firstname, String lastname, String email, String password) {
2535 LDAPConnection lc = new LDAPConnection();
2536 LDAPAttributeSet attributeSet = new LDAPAttributeSet();
2537 attributeSet.add(new LDAPAttribute("objectClass", getConfiguration().getStringArray("objectClass")));
2538 attributeSet.add(new LDAPAttribute("uid", username));
2539 attributeSet.add(new LDAPAttribute("cn", new String[]{firstname + " " + lastname}));
2540 attributeSet.add(new LDAPAttribute("sn", lastname));
2541 attributeSet.add(new LDAPAttribute("givenName", firstname));
2542 attributeSet.add(new LDAPAttribute("mail", email));
2543 attributeSet.add(new LDAPAttribute("userPassword", password));
2544 String dn = "uid=" + username + "," + getConfiguration().getString("baseDn");
2545 LDAPEntry newEntry = new LDAPEntry(dn, attributeSet);
2547 lc.connect(getConfiguration().getString("ldapHost"), LDAPConnection.DEFAULT_PORT);
2548 lc.bind(LDAPConnection.LDAP_V3, getConfiguration().getString("bindDn"),
2549 getConfiguration().getString("bindPassword").getBytes("UTF8"));
2551 logger.info("Successfully added LDAP account: " + dn);
2553 } catch(LDAPException e) {
2554 throw new RuntimeException(e);
2555 } catch(UnsupportedEncodingException e) {
2556 throw new RuntimeException(e);
2562 public UserClass upgradeUserClass(String username, String code) throws ObjectNotFoundException, InvitationUsedException {
2563 User user = findUser(username);
2565 throw new ObjectNotFoundException("The user was not found");
2566 Invitation invite = findInvite(code);
2567 if (invite.getUser() != null)
2568 throw new InvitationUsedException("This code has already been used");
2569 invite.setUser(user);
2570 UserClass couponClass = getCouponUserClass();
2571 user.setUserClass(couponClass);
2576 public UserClass getCouponUserClass() {
2577 return dao.findCouponUserClass();
2581 * Mark the folder as modified from the specified user and change it's modification date.
2583 private void touchFolder(Folder f, User _user, Date now){
2584 final AuditInfo auditInfo = f.getAuditInfo();
2585 auditInfo.setModificationDate(now);
2586 auditInfo.setModifiedBy(_user);
2587 f.setAuditInfo(auditInfo);
2591 * Mark the file as modified from the specified user and change it's modification date.
2593 private void touchFile(FileHeader f, User _user, Date now){
2594 final AuditInfo auditInfo = f.getAuditInfo();
2595 auditInfo.setModificationDate(now);
2596 auditInfo.setModifiedBy(_user);
2597 f.setAuditInfo(auditInfo);
2601 * Set the provided readForAll as the new readforAll value of the specified
2602 * folder and sub-folders.
2607 * @throws ObjectNotFoundException
2610 private void setFolderReadForAll(User user, Folder folder, Boolean readForAll){
2611 if (readForAll != null && user.equals(folder.getOwner())){
2612 folder.setReadForAll(readForAll);
2614 for (FileHeader file : folder.getFiles())
2615 file.setReadForAll(readForAll);
2617 //only update subfolders when readforall is true. otherwise all sub-folders stay untouched
2618 for (Folder sub : folder.getSubfolders())
2619 setFolderReadForAll(user, sub, readForAll);
2626 * Update the userLogin with the values from the supplied object.
2629 public void addUserLogin(UserLogin userLogin) {
2630 dao.update(userLogin);
2635 * Retrieves the current session user login and the user's last login
2638 * @return a list of last two user logins
2639 * @throws ObjectNotFoundException
2642 public List<UserLogin> getUserLogins(Long userId) throws ObjectNotFoundException{
2643 List<UserLogin> userLoginResults = new ArrayList<UserLogin>();
2644 userLoginResults = dao.getLoginsForUser(userId);
2645 if(userLoginResults.size() == 0)
2646 throw new ObjectNotFoundException("No userlogin found for the user");
2647 //if the user logins for the first time lastLoginDate = currentLoginDate
2648 if(userLoginResults.size()==1)
2649 userLoginResults.add(userLoginResults.get(0));
2650 return userLoginResults;
2655 public void postFileToSolr(CommonsHttpSolrServer solr, Long id) {
2657 FileHeader file = dao.getFileForIndexing(id);
2658 FileBody body = file.getCurrentBody();
2659 String mime = body.getMimeType();
2660 boolean multipart = true;
2661 if (!mime.equals("application/pdf")
2662 && !mime.equals("text/plain")
2663 && !mime.equals("text/html")
2664 && !mime.endsWith("msword")
2665 && !mime.endsWith("ms-excel")
2666 && !mime.endsWith("powerpoint")
2667 || (body.getFileSize() > getConfiguration().getLong("solrDocumentUploadLimitInKB") * 1024))
2671 sendMetaDataOnly(solr, file);
2673 ContentStreamUpdateRequest solrRequest = new ContentStreamUpdateRequest(getConfiguration().getString("solr.rich.update.path"));
2674 solrRequest.setParam("literal.id", file.getId().toString());
2675 solrRequest.setParam("literal.name", file.getName());
2676 for (FileTag t : file.getFileTags()) {
2677 solrRequest.getParams().add("literal.tag", t.getTag());
2679 for (Permission p : file.getPermissions()) {
2681 if (p.getUser() != null)
2682 solrRequest.setParam("literal.ureaders", p.getUser().getId().toString());
2683 else if (p.getGroup() != null)
2684 solrRequest.setParam("literal.greaders", p.getGroup().getId().toString());
2687 solrRequest.setParam("literal.owner", file.getOwner().getId().toString());
2688 solrRequest.setParam("literal.public", String.valueOf(file.isReadForAll()));
2689 File fsFile = new File(body.getStoredFilePath());
2690 solrRequest.addFile(fsFile);
2692 solr.request(solrRequest);
2694 catch (SolrException e) {
2695 logger.warn("File " + id + " failed with SolrException: " + e.getLocalizedMessage() + ". Retrying without the file");
2696 //Let 's try without the file
2697 sendMetaDataOnly(solr, file);
2699 catch (NullPointerException e) {
2700 logger.warn("File " + id + " failed with NullPointerException: " + e.getLocalizedMessage() + ". Retrying without the file");
2701 //Let 's try without the file
2702 sendMetaDataOnly(solr, file);
2704 catch (SolrServerException e) {
2705 logger.warn("File " + id + " failed with SolrServerException: " + e.getLocalizedMessage() + ". Retrying without the file");
2706 //Let 's try without the file
2707 sendMetaDataOnly(solr, file);
2710 } catch (MalformedURLException e) {
2711 throw new EJBException(e);
2712 } catch (ObjectNotFoundException e) {
2713 logger.error("Indexing of file id " + id + " failed.", e);
2714 } catch (SolrServerException e) {
2715 throw new EJBException(e);
2716 } catch (IOException e) {
2717 throw new EJBException(e);
2721 private void sendMetaDataOnly(CommonsHttpSolrServer solr, FileHeader file) throws SolrServerException, IOException {
2722 SolrInputDocument solrDoc = new SolrInputDocument();
2723 solrDoc.addField("id", file.getId().toString());
2724 solrDoc.addField("name", file.getName());
2725 for (FileTag t : file.getFileTags()) {
2726 solrDoc.addField("tag", t.getTag());
2728 for (Permission p : file.getPermissions()) {
2730 if (p.getUser() != null)
2731 solrDoc.addField("ureaders", p.getUser().getId());
2732 else if (p.getGroup() != null)
2733 solrDoc.addField("greaders", p.getGroup().getId());
2736 solrDoc.addField("owner", file.getOwner().getId());
2737 solrDoc.addField("public", file.isReadForAll());
2741 private String tokenizeFilename(String filename){
2742 StringBuffer result = new StringBuffer();
2743 StringTokenizer tokenizer = new StringTokenizer(filename,"._");
2744 while(tokenizer.hasMoreTokens()){
2745 result.append(tokenizer.nextToken());
2748 result.append(filename);
2749 return result.toString();
2752 private String normalizeSearchQuery(String query) {
2753 if (query.contains("*"))
2754 return query.toLowerCase().replace('ά', 'α').replace('έ', 'ε').replace('ί', 'ι').replace('ή', 'η').replace('ύ', 'υ')
2755 .replace('ό', 'ο').replace('ς', 'σ').replace('ώ', 'ω').replace('ϊ', 'ι').replace('ϋ', 'υ');
2760 private String escapeCharacters(String text) {
2761 return text.replaceAll(":", "\\\\:");