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.dto.FileBodyDTO;
41 import gr.ebs.gss.server.domain.dto.FileHeaderDTO;
42 import gr.ebs.gss.server.domain.dto.FolderDTO;
43 import gr.ebs.gss.server.domain.dto.GroupDTO;
44 import gr.ebs.gss.server.domain.dto.PermissionDTO;
45 import gr.ebs.gss.server.domain.dto.StatsDTO;
46 import gr.ebs.gss.server.domain.dto.UserDTO;
49 import java.io.FileInputStream;
50 import java.io.FileNotFoundException;
51 import java.io.FileOutputStream;
52 import java.io.IOException;
53 import java.io.InputStream;
54 import java.io.StringWriter;
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;
86 import javax.xml.parsers.DocumentBuilder;
87 import javax.xml.parsers.DocumentBuilderFactory;
88 import javax.xml.parsers.ParserConfigurationException;
89 import javax.xml.transform.OutputKeys;
90 import javax.xml.transform.Transformer;
91 import javax.xml.transform.TransformerConfigurationException;
92 import javax.xml.transform.TransformerException;
93 import javax.xml.transform.TransformerFactory;
94 import javax.xml.transform.dom.DOMSource;
95 import javax.xml.transform.stream.StreamResult;
97 import org.apache.commons.configuration.Configuration;
98 import org.apache.commons.httpclient.HttpClient;
99 import org.apache.commons.httpclient.HttpException;
100 import org.apache.commons.httpclient.NameValuePair;
101 import org.apache.commons.httpclient.methods.GetMethod;
102 import org.apache.commons.httpclient.methods.PostMethod;
103 import org.apache.commons.httpclient.methods.StringRequestEntity;
104 import org.apache.commons.lang.StringUtils;
105 import org.apache.commons.logging.Log;
106 import org.apache.commons.logging.LogFactory;
107 import org.apache.solr.client.solrj.SolrServerException;
108 import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
109 import org.apache.solr.client.solrj.request.AbstractUpdateRequest;
110 import org.apache.solr.client.solrj.request.ContentStreamUpdateRequest;
111 import org.apache.solr.common.SolrException;
112 import org.apache.solr.common.SolrInputDocument;
113 import org.hibernate.exception.ConstraintViolationException;
114 import org.w3c.dom.DOMException;
115 import org.w3c.dom.Document;
116 import org.w3c.dom.Node;
117 import org.w3c.dom.NodeList;
118 import org.xml.sax.SAXException;
120 import com.novell.ldap.LDAPAttribute;
121 import com.novell.ldap.LDAPAttributeSet;
122 import com.novell.ldap.LDAPConnection;
123 import com.novell.ldap.LDAPEntry;
124 import com.novell.ldap.LDAPException;
127 * The concrete implementation of the ExternalAPI interface.
132 public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
134 * The default MIME type for files without an explicit one.
136 private static final String DEFAULT_MIME_TYPE = "application/octet-stream";
139 * The size of the buffer that is used to temporarily store chunks of
140 * uploaded files, while storing them to the file repository.
142 private static final int UPLOAD_BUFFER_SIZE = 1024 * 4;
147 private static Log logger = LogFactory.getLog(ExternalAPIBean.class);
150 * Injected reference to the GSSDAO data access facade.
157 * A cached random number generator for creating unique filenames.
159 private static Random random = new Random();
162 * Mark the folder and all of its parent folders as modified from the specified user.
164 private void touchParentFolders(Folder folder, User user, Date date) {
167 AuditInfo ai = f.getAuditInfo();
168 ai.setModifiedBy(user);
169 ai.setModificationDate(date);
176 public FolderDTO getRootFolder(Long userId) throws ObjectNotFoundException {
178 throw new ObjectNotFoundException("No user specified");
179 Folder folder = dao.getRootFolder(userId);
180 return folder.getDTO();
184 public FolderDTO getFolder(final Long userId, final Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
186 throw new ObjectNotFoundException("No user specified");
187 if (folderId == null)
188 throw new ObjectNotFoundException("No folder specified");
189 final User user = dao.getEntityById(User.class, userId);
190 final Folder folder = dao.getEntityById(Folder.class, folderId);
192 if (!folder.hasReadPermission(user))
193 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
194 return folder.getDTO();
198 public User getUser(Long userId) throws ObjectNotFoundException {
200 throw new ObjectNotFoundException("No user specified");
201 return dao.getEntityById(User.class, userId);
205 public UserDTO getUserDTO(final Long userId) throws ObjectNotFoundException {
206 return getUser(userId).getDTO();
210 public GroupDTO getGroup(final Long groupId) throws ObjectNotFoundException {
212 throw new ObjectNotFoundException("No group specified");
213 final Group group = dao.getEntityById(Group.class, groupId);
214 return group.getDTO();
218 public GroupDTO getGroup(Long userId, String name) throws ObjectNotFoundException {
220 throw new ObjectNotFoundException("No user specified");
222 throw new ObjectNotFoundException("No group specified");
223 User user = dao.getEntityById(User.class, userId);
224 List<Group> groups = user.getGroupsSpecified();
225 for (Group group: groups)
226 if (group.getName().equals(name))
227 return group.getDTO();
228 throw new ObjectNotFoundException("Group " + name + " not found");
232 public List<GroupDTO> getGroups(final Long userId) throws ObjectNotFoundException {
234 throw new ObjectNotFoundException("No user specified");
235 final List<Group> groups = dao.getGroups(userId);
236 final List<GroupDTO> result = new ArrayList<GroupDTO>();
237 for (final Group g : groups)
238 result.add(g.getDTO());
243 public List<FileHeaderDTO> getFiles(Long userId, Long folderId, boolean ignoreDeleted)
244 throws ObjectNotFoundException, InsufficientPermissionsException {
247 throw new ObjectNotFoundException("No user specified");
248 if (folderId == null)
249 throw new ObjectNotFoundException("No folder specified");
250 User user = dao.getEntityById(User.class, userId);
251 Folder folder = dao.getEntityById(Folder.class, folderId);
252 if (!folder.hasReadPermission(user))
253 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
254 // Do the actual work.
255 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
256 List<FileHeader> files = dao.getFiles(folderId, userId, ignoreDeleted);
257 for (FileHeader f : files)
258 result.add(f.getDTO());
263 public List<UserDTO> getUsers(final Long userId, final Long groupId) throws ObjectNotFoundException {
266 throw new ObjectNotFoundException("No user specified");
268 throw new ObjectNotFoundException("No group specified");
270 // Do the actual work.
271 final List<User> users = dao.getUsers(groupId);
272 final List<UserDTO> result = new ArrayList<UserDTO>();
273 for (final User u : users)
274 result.add(u.getDTO());
279 public FolderDTO createFolder(Long userId, Long parentId, String name)
280 throws DuplicateNameException, ObjectNotFoundException, InsufficientPermissionsException {
283 throw new ObjectNotFoundException("No user specified");
284 if (StringUtils.isEmpty(name))
285 throw new ObjectNotFoundException("New folder name is empty");
286 if (parentId == null)
287 throw new ObjectNotFoundException("No parent specified");
288 if (dao.existsFolderOrFile(parentId, name))
289 throw new DuplicateNameException("A folder or file with the name '" +
290 name + "' already exists at this level");
292 User creator = dao.getEntityById(User.class, userId);
294 Folder parent = null;
296 parent = dao.getEntityById(Folder.class, parentId);
297 } catch (ObjectNotFoundException onfe) {
298 // Supply a more accurate problem description.
299 throw new ObjectNotFoundException("Parent folder not found");
301 if (!parent.hasWritePermission(creator))
302 throw new InsufficientPermissionsException("You don't have the permissions" +
303 " to write to this folder");
305 // Do the actual work.
306 return createFolder(name, parent, creator);
310 * Create a new folder with the provided name, parent and owner.
315 * @return the new folder
317 private FolderDTO createFolder(String name, Folder parent, User creator) {
318 Folder folder = new Folder();
319 folder.setName(name);
320 if (parent != null) {
321 parent.addSubfolder(folder);
322 folder.setOwner(parent.getOwner());
324 folder.setOwner(creator);
326 Date now = new Date();
327 AuditInfo auditInfo = new AuditInfo();
328 auditInfo.setCreatedBy(creator);
329 auditInfo.setCreationDate(now);
330 auditInfo.setModifiedBy(creator);
331 auditInfo.setModificationDate(now);
332 folder.setAuditInfo(auditInfo);
333 touchParentFolders(folder, auditInfo.getModifiedBy(), auditInfo.getModificationDate());
336 for (Permission p : parent.getPermissions()) {
337 Permission permission = new Permission();
338 permission.setGroup(p.getGroup());
339 permission.setUser(p.getUser());
340 permission.setRead(p.getRead());
341 permission.setWrite(p.getWrite());
342 permission.setModifyACL(p.getModifyACL());
343 folder.addPermission(permission);
346 Permission permission = new Permission();
347 permission.setUser(creator);
348 permission.setRead(true);
349 permission.setWrite(true);
350 permission.setModifyACL(true);
351 folder.addPermission(permission);
355 folder.setReadForAll(parent.isReadForAll());
358 return folder.getDTO();
362 public void deleteFolder(final Long userId, final Long folderId) throws InsufficientPermissionsException, ObjectNotFoundException {
365 throw new ObjectNotFoundException("No user specified");
366 if (folderId == null)
367 throw new ObjectNotFoundException("No folder specified");
369 // Do the actual work.
370 final Folder folder = dao.getEntityById(Folder.class, folderId);
371 final Folder parent = folder.getParent();
373 throw new ObjectNotFoundException("Deleting the root folder is not allowed");
374 final User user = dao.getEntityById(User.class, userId);
375 if (!folder.hasDeletePermission(user)) {
376 logger.info("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
377 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
379 removeSubfolderFiles(folder);
380 parent.removeSubfolder(folder);
382 touchParentFolders(parent, user, new Date());
386 * Traverses the folder and deletes all actual files (file system)
387 * regardless of permissions
391 private void removeSubfolderFiles(Folder folder) {
392 //remove files for all subfolders
393 for (Folder subfolder:folder.getSubfolders())
394 removeSubfolderFiles(subfolder);
395 //remove this folder's file bodies (actual files)
396 for (FileHeader file:folder.getFiles()) {
397 for (FileBody body:file.getBodies())
398 deleteActualFile(body.getStoredFilePath());
399 indexFile(file.getId(), true);
404 @SuppressWarnings("unchecked")
405 public List<FolderDTO> getSubfolders(Long userId, Long folderId)
406 throws ObjectNotFoundException, InsufficientPermissionsException {
408 throw new ObjectNotFoundException("No user specified");
409 if (folderId == null)
410 throw new ObjectNotFoundException("No folder specified");
411 User user = dao.getEntityById(User.class, userId);
412 Folder folder = dao.getEntityById(Folder.class, folderId);
413 if (!folder.hasReadPermission(user))
414 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
415 List<FolderDTO> result = new ArrayList<FolderDTO>();
416 if (folder.hasReadPermission(user))
417 for (Folder f : folder.getSubfolders())
418 if (f.hasReadPermission(user) && !f.isDeleted())
419 result.add(f.getDTO());
424 public FolderDTO updateFolder(Long userId, Long folderId, String folderName,
426 Set<PermissionDTO> permissions)
427 throws InsufficientPermissionsException, ObjectNotFoundException,
428 DuplicateNameException {
432 throw new ObjectNotFoundException("No user specified");
433 if (folderId == null)
434 throw new ObjectNotFoundException("No folder specified");
436 Folder folder = dao.getEntityById(Folder.class, folderId);
437 User user = dao.getEntityById(User.class, userId);
438 if (folderName != null && !folder.hasWritePermission(user))
439 throw new InsufficientPermissionsException("You don't have the necessary permissions");
440 if(permissions != null && !permissions.isEmpty() && !folder.hasModifyACLPermission(user))
441 throw new InsufficientPermissionsException("You don't have the necessary permissions");
442 // Check permissions for making file public.
443 if (readForAll != null && !user.equals(folder.getOwner()))
444 throw new InsufficientPermissionsException("Only the owner can make a folder public or not public");
446 Folder parent = folder.getParent();
447 if (folderName != null) {
449 if (!folder.getName().equals(folderName) && dao.existsFolderOrFile(parent.getId(), folderName))
450 throw new DuplicateNameException("A folder or file with the name '" + folderName + "' already exists at this level");
452 // Do the actual modification.
453 folder.setName(folderName);
455 if (permissions != null)
456 setFolderPermissions(user, folder, permissions);
457 if (readForAll != null)
458 setFolderReadForAll(user, folder, readForAll);
459 folder.getAuditInfo().setModificationDate(new Date());
460 folder.getAuditInfo().setModifiedBy(user);
462 touchParentFolders(folder, user, new Date());
463 return folder.getDTO();
467 public void createGroup(final Long userId, final String name) throws ObjectNotFoundException, DuplicateNameException {
470 throw new ObjectNotFoundException("No user specified");
471 if (StringUtils.isEmpty(name))
472 throw new ObjectNotFoundException("New group name is empty");
473 if (name.indexOf('/')>=0)
474 throw new IllegalArgumentException("Character '/' is not allowed in group name");
475 if (dao.existsGroup(userId, name))
476 throw new DuplicateNameException("A group with the name '" + name + "' already exists");
478 // TODO: Check permissions
480 final User owner = dao.getEntityById(User.class, userId);
482 // Do the actual work.
483 owner.createGroup(name);
487 public void deleteGroup(final Long userId, final Long groupId) throws ObjectNotFoundException, InsufficientPermissionsException {
490 throw new ObjectNotFoundException("No user specified");
492 throw new ObjectNotFoundException("No group specified");
494 // Do the actual work.
495 final User owner = dao.getEntityById(User.class, userId);
496 final Group group = dao.getEntityById(Group.class, groupId);
497 final Date now = new Date();
498 // Only delete the group if actually owned by the user.
499 if (group.getOwner().equals(owner)) {
500 List<Folder> folders = dao.getFoldersPermittedForGroup(userId, groupId);
501 for (Folder f : folders){
502 f.getPermissions().removeAll(group.getPermissions());
503 touchFolder(f, owner, now);
504 for(FileHeader file : f.getFiles()){
505 file.getPermissions().removeAll(group.getPermissions());
506 touchFile(file, owner, now);
509 List<FileHeader> files = dao.getFilesPermittedForGroup(userId, groupId);
510 for(FileHeader h : files){
511 h.getPermissions().removeAll(group.getPermissions());
512 touchFile(h, owner, now);
514 owner.removeSpecifiedGroup(group);
517 else throw new InsufficientPermissionsException("You are not the owner of this group");
521 public FileHeaderDTO createFile(Long userId, Long folderId, String name, String mimeType, InputStream stream)
522 throws DuplicateNameException, ObjectNotFoundException, GSSIOException,
523 InsufficientPermissionsException, QuotaExceededException {
526 file = uploadFile(stream, userId);
527 } catch ( IOException ioe) {
528 // Supply a more accurate problem description.
529 throw new GSSIOException("Problem creating file",ioe);
531 return createFile(userId, folderId, name, mimeType, file.length(), file.getAbsolutePath());
535 * @see gr.ebs.gss.server.ejb.ExternalAPIRemote#indexFile(java.lang.Long, boolean)
538 public void indexFile(Long fileId, boolean delete) {
539 Connection qConn = null;
540 Session session = null;
541 MessageProducer sender = null;
543 Context jndiCtx = new InitialContext();
544 ConnectionFactory factory = (QueueConnectionFactory) jndiCtx.lookup("java:/JmsXA");
545 Queue queue = (Queue) jndiCtx.lookup("queue/gss-indexingQueue");
546 qConn = factory.createConnection();
547 session = qConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
548 sender = session.createProducer(queue);
550 MapMessage map = session.createMapMessage();
551 map.setObject("id", fileId);
552 map.setBoolean("delete", delete);
555 catch (NamingException e) {
556 logger.error("Index was not updated: ", e);
558 catch (JMSException e) {
559 logger.error("Index was not updated: ", e);
570 catch (JMSException e) {
579 * A helper method that generates a unique file path for a stored file. The
580 * files are stored using random hash names that are distributed evenly in
581 * a 2-level tree of subdirectories named after the first two hex characters
582 * in the name. For example, file ab1234cd5769f will be stored in the path
583 * /file-repository-root/a/b/ab1234cd5769f. The directories will be created
584 * if they don't already exist.
586 * @return a unique new file path
588 private String generateRepositoryFilePath() {
589 String filename = Long.toHexString(random.nextLong());
590 String fileRepositoryPath = getConfiguration().getString("fileRepositoryPath","/tmp");
591 File root = new File(fileRepositoryPath);
594 File firstFolder = new File(root + File.separator + filename.substring(0, 1));
595 if (!firstFolder.exists())
597 File secondFolder = new File(firstFolder + File.separator + filename.substring(1, 2));
598 if (!secondFolder.exists())
599 secondFolder.mkdir();
600 return secondFolder + File.separator + filename;
604 public void deleteFile(final Long userId, final Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
607 throw new ObjectNotFoundException("No user specified");
609 throw new ObjectNotFoundException("No file specified");
611 // Do the actual work.
612 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
613 final Folder parent = file.getFolder();
615 throw new ObjectNotFoundException("The specified file has no parent folder");
616 final User user = dao.getEntityById(User.class, userId);
617 if (!file.hasDeletePermission(user))
618 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
619 for (final FileBody body : file.getBodies())
620 deleteActualFile(body.getStoredFilePath());
622 touchParentFolders(parent, user, new Date());
623 indexFile(fileId, true);
627 public void deleteActualFile(String path) {
630 File file = new File(path);
632 logger.error("Could not delete file " + path);
636 public void createTag(final Long userId, final Long fileHeaderId, final String tag) throws ObjectNotFoundException {
638 throw new ObjectNotFoundException("No user specified");
639 if (fileHeaderId == null)
640 throw new ObjectNotFoundException("No file specified");
641 if (StringUtils.isEmpty(tag))
642 throw new ObjectNotFoundException("Tag is empty");
644 final User user = dao.getEntityById(User.class, userId);
645 final FileHeader fh = dao.getEntityById(FileHeader.class, fileHeaderId);
646 final Folder parent = fh.getFolder();
648 throw new ObjectNotFoundException("The specified file has no parent folder");
649 user.addTag(fh, tag);
650 touchParentFolders(parent, user, new Date());
654 public Set<String> getUserTags(final Long userId) throws ObjectNotFoundException {
655 return dao.getUserTags(userId);
659 public void updateFile(Long userId, Long fileId, String name,
660 String tagSet, Date modificationDate, Boolean versioned,
661 Boolean readForAll, Set<PermissionDTO> permissions)
662 throws DuplicateNameException, ObjectNotFoundException, InsufficientPermissionsException {
664 throw new ObjectNotFoundException("No user specified");
666 throw new ObjectNotFoundException("No file specified");
667 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
668 final Folder parent = file.getFolder();
670 throw new ObjectNotFoundException("The specified file has no parent folder");
672 User user = dao.getEntityById(User.class, userId);
673 // Check permissions for modifying the file metadata.
674 if ((name != null || tagSet != null || modificationDate != null || versioned != null) && !file.hasWritePermission(user))
675 throw new InsufficientPermissionsException("User " + user.getId() + " cannot update file " + file.getName() + "(" + file.getId() + ")");
676 // Check permissions for making file public.
677 if (readForAll != null && !user.equals(file.getOwner()))
678 throw new InsufficientPermissionsException("Only the owner can make a file public or not public");
679 // Check permissions for modifying the ACL.
680 if(permissions != null && !permissions.isEmpty() && !file.hasModifyACLPermission(user))
681 throw new InsufficientPermissionsException("User " + user.getId() + " cannot update the permissions on file " + file.getName() + "(" + file.getId() + ")");
684 // Do plain check for file already exists.
685 // Extreme concurrency case should be caught by constraint violation later.
686 if (dao.existsFolderOrFile(parent.getId(), name)) throw new DuplicateNameException("A file or folder with the name '" + name + "' already exists");
690 if (modificationDate != null)
691 file.getAuditInfo().setModificationDate(modificationDate);
693 file.getAuditInfo().setModificationDate(new Date());
694 file.getAuditInfo().setModifiedBy(user);
696 List<FileTag> tags = file.getFileTags();
697 if (tagSet != null) {
698 Iterator<FileTag> i = tags.iterator();
699 while (i.hasNext()) {
700 FileTag tag = i.next();
707 StringTokenizer st = new StringTokenizer(tagSet, ",");
708 while (st.hasMoreTokens())
709 new FileTag(user, file, st.nextToken().trim());
711 if (versioned != null && !file.isVersioned() == versioned) {
712 if (file.isVersioned())
713 removeOldVersions(userId, fileId);
714 file.setVersioned(versioned);
716 if (readForAll != null && user.equals(file.getOwner()))
717 file.setReadForAll(readForAll);
718 if (permissions != null && !permissions.isEmpty())
719 setFilePermissions(file, permissions);
722 * Force constraint violation to manifest itself here.
723 * This should cover extreme concurrency cases that the simple check
724 * above hasn't caught.
729 catch (EJBTransactionRolledbackException e) {
730 Throwable cause = e.getCause();
731 if (cause instanceof PersistenceException && cause.getCause() instanceof ConstraintViolationException)
732 throw new DuplicateNameException("A file or folder with the name '" + name + "' already exists");
736 touchParentFolders(parent, user, new Date());
738 // Re-index the file if it was modified.
739 if (name != null || tagSet != null)
740 indexFile(fileId, false);
744 public InputStream getFileContents(Long userId, Long fileId)
745 throws ObjectNotFoundException, InsufficientPermissionsException {
747 throw new ObjectNotFoundException("No user specified");
749 throw new ObjectNotFoundException("No file specified");
751 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
752 User user = dao.getEntityById(User.class, userId);
753 if (!header.hasReadPermission(user)) {
754 logger.info("User " + user.getId() + " cannot read file " + header.getName() + "(" + fileId + ")");
755 throw new InsufficientPermissionsException("You don't have the necessary permissions");
758 File f = new File(header.getCurrentBody().getStoredFilePath());
760 return new FileInputStream(f);
761 } catch (FileNotFoundException e) {
762 logger.error("Could not locate the contents of file " + f.getAbsolutePath());
763 throw new ObjectNotFoundException("The file contents could not be located");
768 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFileContents(java.lang.Long, java.lang.Long, java.lang.Long)
771 public InputStream getFileContents(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
773 throw new ObjectNotFoundException("No user specified");
775 throw new ObjectNotFoundException("No file specified");
777 throw new ObjectNotFoundException("No file specified");
779 final FileHeader header = dao.getEntityById(FileHeader.class, fileId);
780 final FileBody body = dao.getEntityById(FileBody.class, bodyId);
781 final User user = dao.getEntityById(User.class, userId);
782 if (!header.hasReadPermission(user)) {
783 logger.info("User " + user.getId() + " cannot read file " + header.getName() + "(" + fileId + ")");
784 throw new InsufficientPermissionsException("You don't have the necessary permissions");
787 File f = new File(body.getStoredFilePath());
789 return new FileInputStream(f);
790 } catch (FileNotFoundException e) {
791 logger.error("Could not locate the contents of file " + f.getAbsolutePath());
792 throw new ObjectNotFoundException("The file contents could not be located");
797 public FileHeaderDTO getFile(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
799 throw new ObjectNotFoundException("No user specified");
801 throw new ObjectNotFoundException("No file specified");
802 final User user = dao.getEntityById(User.class, userId);
803 final 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 return file.getDTO();
810 public FileBodyDTO getFileBody(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
812 throw new ObjectNotFoundException("No user specified");
814 throw new ObjectNotFoundException("No file specified");
815 User user = dao.getEntityById(User.class, userId);
816 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
817 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
818 throw new InsufficientPermissionsException("You don't have the necessary permissions");
819 FileBody body = dao.getEntityById(FileBody.class, bodyId);
820 return body.getDTO();
824 public Object getResourceAtPath(Long ownerId, String path, boolean ignoreDeleted)
825 throws ObjectNotFoundException {
827 throw new ObjectNotFoundException("No user specified");
828 if (StringUtils.isEmpty(path))
829 throw new ObjectNotFoundException("No path specified");
831 User owner = dao.getEntityById(User.class, ownerId);
832 List<String> pathElements = new ArrayList<String>();
833 StringTokenizer st = new StringTokenizer(path, "/");
834 while (st.hasMoreTokens())
835 pathElements.add(st.nextToken());
836 if (pathElements.size() < 1)
837 return getRootFolder(owner.getId());
838 // Store the last element, since it requires special handling.
839 String lastElement = pathElements.remove(pathElements.size() - 1);
840 FolderDTO cursor = getRootFolder(owner.getId());
841 // Traverse and verify the specified folder path.
842 for (String pathElement : pathElements) {
843 cursor = getFolder(cursor.getId(), pathElement);
844 if (cursor.isDeleted())
845 throw new ObjectNotFoundException("Folder " + cursor.getPath() + " not found");
848 // Use the lastElement to retrieve the actual resource.
849 Object resource = null;
851 FileHeaderDTO file = getFile(cursor.getId(), lastElement);
852 if (ignoreDeleted && file.isDeleted())
853 throw new ObjectNotFoundException("Resource not found");
855 } catch (ObjectNotFoundException e) {
856 // Perhaps the requested resource is not a file, so
857 // check for folders as well.
858 FolderDTO folder = getFolder(cursor.getId(), lastElement);
859 if (ignoreDeleted && folder.isDeleted())
860 throw new ObjectNotFoundException("Resource not found");
867 * Retrieve a file for the specified user that has the specified name and
868 * its parent folder has id equal to folderId.
870 * @param userId the ID of the current user
871 * @param folderId the ID of the parent folder
872 * @param name the name of the requested file
873 * @return the file found
874 * @throws ObjectNotFoundException if the specified folder or file was not
875 * found, with the exception message mentioning the precise
878 private FileHeaderDTO getFile(Long folderId, String name) throws ObjectNotFoundException {
879 if (folderId == null)
880 throw new ObjectNotFoundException("No parent folder specified");
881 if (StringUtils.isEmpty(name))
882 throw new ObjectNotFoundException("No file specified");
884 FileHeader file = dao.getFile(folderId, name);
885 return file.getDTO();
889 * Retrieve a folder for the specified user that has the specified name and
890 * its parent folder has id equal to parentId.
892 * @param parentId the ID of the parent folder
893 * @param name the name of the requested folder
894 * @return the folder found
895 * @throws ObjectNotFoundException if the specified folder or parent was not
896 * found, with the exception message mentioning the precise
899 private FolderDTO getFolder(Long parentId, String name) throws ObjectNotFoundException {
900 if (parentId == null)
901 throw new ObjectNotFoundException("No parent folder specified");
902 if (StringUtils.isEmpty(name))
903 throw new ObjectNotFoundException("No folder specified");
905 Folder folder = dao.getFolder(parentId, name);
906 return folder.getDTO();
909 private FileHeaderDTO updateFileContents(Long userId, Long fileId, String mimeType, InputStream resourceInputStream) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
912 file = uploadFile(resourceInputStream, userId);
913 } catch ( IOException ioe) {
914 // Supply a more accurate problem description.
915 throw new GSSIOException("Problem creating file",ioe);
917 return updateFileContents(userId, fileId, mimeType, file.length(), file.getAbsolutePath());
921 public void copyFile(Long userId, Long fileId, String dest) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
923 throw new ObjectNotFoundException("No user specified");
925 throw new ObjectNotFoundException("No file specified");
926 if (StringUtils.isEmpty(dest))
927 throw new ObjectNotFoundException("No destination specified");
929 Object destination = getResourceAtPath(userId, getParentPath(dest), true);
930 if (!(destination instanceof FolderDTO))
931 throw new ObjectNotFoundException("Destination parent folder not found");
932 FolderDTO parent = (FolderDTO) destination;
933 copyFile(userId, fileId, parent.getId(), getLastElement(dest));
937 public void copyFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
939 throw new ObjectNotFoundException("No user specified");
941 throw new ObjectNotFoundException("No owner specified");
943 throw new ObjectNotFoundException("No file specified");
944 if (StringUtils.isEmpty(dest))
945 throw new ObjectNotFoundException("No destination specified");
947 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
948 if (!(destination instanceof FolderDTO))
949 throw new ObjectNotFoundException("Destination parent folder not found");
950 FolderDTO parent = (FolderDTO) destination;
951 copyFile(userId, fileId, parent.getId(), getLastElement(dest));
955 public void copyFile(Long userId, Long fileId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
957 throw new ObjectNotFoundException("No user specified");
959 throw new ObjectNotFoundException("No file specified");
961 throw new ObjectNotFoundException("No destination specified");
962 if (StringUtils.isEmpty(destName))
963 throw new ObjectNotFoundException("No destination file name specified");
965 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
966 Folder destination = dao.getEntityById(Folder.class, destId);
967 User user = dao.getEntityById(User.class, userId);
968 if (!file.hasReadPermission(user) || !destination.hasWritePermission(user))
969 throw new InsufficientPermissionsException("You don't have the necessary permissions");
970 boolean versioned = file.isVersioned();
971 int versionsNumber = file.getBodies().size();
972 FileBody oldestBody = file.getBodies().get(0);
973 assert oldestBody != null;
974 File contents = new File(oldestBody.getStoredFilePath());
976 createFile(user.getId(), destination.getId(), destName, oldestBody.getMimeType(), new FileInputStream(contents));
977 FileHeader copiedFile = dao.getFile(destination.getId(), destName);
978 copiedFile.setVersioned(versioned);
980 if (versionsNumber > 1)
981 for (int i = 1; i < versionsNumber; i++) {
982 FileBody body = file.getBodies().get(i);
984 contents = new File(body.getStoredFilePath());
985 updateFileContents(user.getId(), copiedFile.getId(), body.getMimeType(), new FileInputStream(contents));
987 List<FileTag> tags = file.getFileTags();
988 for (FileTag tag : tags)
989 createTag(userId, copiedFile.getId(), tag.getTag());
991 } catch (FileNotFoundException e) {
992 throw new ObjectNotFoundException("File contents not found for file " + contents.getAbsolutePath());
998 public void copyFolder(Long userId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
1000 throw new ObjectNotFoundException("No user specified");
1001 if (folderId == null)
1002 throw new ObjectNotFoundException("No folder specified");
1003 if (StringUtils.isEmpty(dest))
1004 throw new ObjectNotFoundException("No destination specified");
1006 Object destination = getResourceAtPath(userId, getParentPath(dest), true);
1007 if (!(destination instanceof FolderDTO))
1008 throw new ObjectNotFoundException("Destination folder not found");
1009 FolderDTO parent = (FolderDTO) destination;
1010 copyFolder(userId, folderId, parent.getId(), getLastElement(dest));
1014 public void copyFolder(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
1016 throw new ObjectNotFoundException("No user specified");
1017 if (folderId == null)
1018 throw new ObjectNotFoundException("No folder specified");
1020 throw new ObjectNotFoundException("No destination specified");
1021 if (StringUtils.isEmpty(destName))
1022 throw new ObjectNotFoundException("No destination folder name specified");
1023 Folder folder = dao.getEntityById(Folder.class, folderId);
1024 Folder destination = dao.getEntityById(Folder.class, destId);
1025 User user = dao.getEntityById(User.class, userId);
1026 if (!destination.hasWritePermission(user) || !folder.hasReadPermission(user))
1027 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1028 createFolder(user.getId(), destination.getId(), destName);
1032 public void copyFolderStructureToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1034 throw new ObjectNotFoundException("No user specified");
1035 if (ownerId == null)
1036 throw new ObjectNotFoundException("No owner specified");
1037 if (folderId == null)
1038 throw new ObjectNotFoundException("No folder specified");
1039 if (StringUtils.isEmpty(dest))
1040 throw new ObjectNotFoundException("No destination specified");
1042 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1043 if (!(destination instanceof FolderDTO))
1044 throw new ObjectNotFoundException("Destination folder not found");
1045 FolderDTO parent = (FolderDTO) destination;
1046 copyFolderStructure(userId, folderId, parent.getId(), getLastElement(dest));
1050 public void copyFolderStructure(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1052 throw new ObjectNotFoundException("No user specified");
1053 if (folderId == null)
1054 throw new ObjectNotFoundException("No folder specified");
1056 throw new ObjectNotFoundException("No destination specified");
1057 if (StringUtils.isEmpty(destName))
1058 throw new ObjectNotFoundException("No destination folder name specified");
1060 Folder folder = dao.getEntityById(Folder.class, folderId);
1061 Folder destination = dao.getEntityById(Folder.class, destId);
1062 final User user = dao.getEntityById(User.class, userId);
1063 // XXX: quick fix need to copy only visible items to user (Source
1065 if (!folder.getOwner().getId().equals(userId) && !folder.hasReadPermission(user))
1067 if(folder.isDeleted())//do not copy trashed folder and contents
1069 if (!destination.hasWritePermission(user) || !folder.hasReadPermission(user))
1070 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1071 createFolder(user.getId(), destination.getId(), destName);
1072 Folder createdFolder = dao.getFolder(destination.getId(), destName);
1073 List<FileHeader> files = folder.getFiles();
1075 for (FileHeader file : files)
1076 if(!file.isDeleted())
1077 copyFile(userId, file.getId(), createdFolder.getId(), file.getName());
1078 List<Folder> subFolders = folder.getSubfolders();
1079 if (subFolders != null)
1080 for (Folder sub : subFolders)
1081 if(!sub.getId().equals(createdFolder.getId()))
1082 copyFolderStructure(userId, sub.getId(), createdFolder.getId(), sub.getName());
1087 * For a provided path, remove the last element and return the rest, that is
1088 * the path of the parent folder.
1090 * @param path the specified path
1091 * @return the path of the parent folder
1092 * @throws ObjectNotFoundException if the provided string contains no path
1095 private String getParentPath(String path) throws ObjectNotFoundException {
1096 int lastDelimiter = path.lastIndexOf('/');
1097 if (lastDelimiter == 0)
1099 if (lastDelimiter == -1)
1101 throw new ObjectNotFoundException("There is no parent in the path: " + path);
1102 else if (lastDelimiter < path.length() - 1)
1103 // Return the part before the delimiter.
1104 return path.substring(0, lastDelimiter);
1106 // Remove the trailing delimiter and then recurse.
1107 String strippedTrail = path.substring(0, lastDelimiter);
1108 return getParentPath(strippedTrail);
1113 * Get the last element in a path that denotes the file or folder name.
1115 * @param path the provided path
1116 * @return the last element in the path
1118 private String getLastElement(String path) {
1119 int lastDelimiter = path.lastIndexOf('/');
1120 if (lastDelimiter == -1)
1123 else if (lastDelimiter < path.length() - 1)
1124 // Return the part after the delimiter.
1125 return path.substring(lastDelimiter + 1);
1127 // Remove the trailing delimiter and then recurse.
1128 String strippedTrail = path.substring(0, lastDelimiter);
1129 return getLastElement(strippedTrail);
1134 public void moveFileToTrash(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1136 throw new ObjectNotFoundException("No user specified");
1138 throw new ObjectNotFoundException("No file specified");
1140 // Do the actual work.
1141 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1142 Folder parent = file.getFolder();
1144 throw new ObjectNotFoundException("The specified file has no parent folder");
1145 User user = dao.getEntityById(User.class, userId);
1146 if (!file.hasDeletePermission(user))
1147 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
1149 file.setDeleted(true);
1151 touchParentFolders(parent, user, new Date());
1155 public void moveFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, InsufficientPermissionsException, QuotaExceededException {
1157 throw new ObjectNotFoundException("No user specified");
1158 if (ownerId == null)
1159 throw new ObjectNotFoundException("No owner specified");
1161 throw new ObjectNotFoundException("No file specified");
1162 if (StringUtils.isEmpty(dest))
1163 throw new ObjectNotFoundException("No destination specified");
1165 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1166 if (!(destination instanceof FolderDTO))
1167 throw new ObjectNotFoundException("Destination parent folder not found");
1168 FolderDTO parent = (FolderDTO) destination;
1169 moveFile(userId, fileId, parent.getId(), getLastElement(dest));
1173 public void moveFile(Long userId, Long fileId, Long destId, String destName) throws InsufficientPermissionsException, ObjectNotFoundException, QuotaExceededException {
1175 throw new ObjectNotFoundException("No user specified");
1177 throw new ObjectNotFoundException("No file specified");
1179 throw new ObjectNotFoundException("No destination specified");
1180 if (StringUtils.isEmpty(destName))
1181 throw new ObjectNotFoundException("No destination file name specified");
1183 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1184 Folder source = file.getFolder();
1185 Folder destination = dao.getEntityById(Folder.class, destId);
1187 User owner = dao.getEntityById(User.class, userId);
1188 if (!file.hasDeletePermission(owner) || !destination.hasWritePermission(owner))
1189 throw new InsufficientPermissionsException("User " + owner.getId() + " cannot move file " + file.getName() + "(" + file.getId() + ")");
1191 // if the destination folder belongs to another user:
1192 if (!file.getOwner().equals(destination.getOwner())) {
1193 // (a) check if the destination quota allows the move
1194 if(getQuotaLeft(destination.getOwner().getId()) < file.getTotalSize())
1195 throw new QuotaExceededException("Not enough free space available");
1196 User newOwner = destination.getOwner();
1197 // (b) if quota OK, change the owner of the file
1198 file.setOwner(newOwner);
1199 // if the file has no permission for the new owner, add it
1200 Permission ownerPermission = null;
1201 for (final Permission p : file.getPermissions())
1202 if (p.getUser() != null)
1203 if (p.getUser().equals(newOwner)) {
1204 ownerPermission = p;
1207 if (ownerPermission == null) {
1208 ownerPermission = new Permission();
1209 ownerPermission.setUser(newOwner);
1210 file.addPermission(ownerPermission);
1212 ownerPermission.setRead(true);
1213 ownerPermission.setWrite(true);
1214 ownerPermission.setModifyACL(true);
1216 // move the file to the destination folder
1217 file.setFolder(destination);
1218 touchParentFolders(source, owner, new Date());
1219 touchParentFolders(destination, owner, new Date());
1223 public void moveFolderToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, InsufficientPermissionsException, QuotaExceededException {
1225 throw new ObjectNotFoundException("No user specified");
1226 if (ownerId == null)
1227 throw new ObjectNotFoundException("No owner specified");
1228 if (folderId == null)
1229 throw new ObjectNotFoundException("No folder specified");
1230 if (StringUtils.isEmpty(dest))
1231 throw new ObjectNotFoundException("No destination specified");
1233 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1234 if (!(destination instanceof FolderDTO))
1235 throw new ObjectNotFoundException("Destination parent folder not found");
1236 FolderDTO parent = (FolderDTO) destination;
1237 moveFolder(userId, folderId, parent.getId(), getLastElement(dest));
1241 public void moveFolder(Long userId, Long folderId, Long destId, String destName)
1242 throws ObjectNotFoundException, InsufficientPermissionsException,
1243 QuotaExceededException {
1244 Folder source = dao.getEntityById(Folder.class, folderId);
1245 Folder destination = dao.getEntityById(Folder.class, destId);
1246 User user = dao.getEntityById(User.class, userId);
1247 User sourceOwner = source.getOwner();
1248 User destinationOwner = destination.getOwner();
1249 // Do not move trashed folders and contents.
1250 if (source.isDeleted())
1252 // Check permissions.
1253 if (!destination.hasWritePermission(user)
1254 || !source.hasReadPermission(user)
1255 || !source.hasWritePermission(user))
1256 throw new InsufficientPermissionsException("You don't have the " +
1257 "necessary permissions");
1258 // Use the same timestamp for all subsequent modifications to make
1259 // changes appear simultaneous.
1260 Date now = new Date();
1261 // If source and destination are not in the same user's namespace,
1262 // change owners and check quota.
1263 if (!sourceOwner.equals(destinationOwner)) {
1264 changeOwner(source, destinationOwner, user, now);
1265 if (getQuotaLeft(destinationOwner.getId()) < 0)
1266 throw new QuotaExceededException("Not enough free space " +
1267 "available in destination folder");
1269 // Perform the move.
1270 Folder oldParent = source.getParent();
1271 oldParent.removeSubfolder(source);
1272 destination.addSubfolder(source);
1273 // Mark the former parent and destination trees upwards as modified.
1274 touchParentFolders(oldParent, user, now);
1275 touchParentFolders(source, user, now);
1279 * Recursively change the owner of the specified folder and all of its
1280 * contents to the specified owner. Also mark them all as modified with the
1281 * specified modifier and modificationDate.
1283 private void changeOwner(Folder folder, User owner, User modifier, Date modificationDate) {
1284 for (FileHeader file: folder.getFiles()) {
1285 file.setOwner(owner);
1286 file.getAuditInfo().setModificationDate(modificationDate);
1287 file.getAuditInfo().setModifiedBy(modifier);
1289 for (Folder sub: folder.getSubfolders())
1290 changeOwner(sub, owner, modifier, modificationDate);
1291 folder.setOwner(owner);
1292 folder.getAuditInfo().setModificationDate(modificationDate);
1293 folder.getAuditInfo().setModifiedBy(modifier);
1297 public List<FileHeaderDTO> getDeletedFiles(Long userId) throws ObjectNotFoundException {
1300 throw new ObjectNotFoundException("No user specified");
1302 // Do the actual work.
1303 final List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1304 final List<FileHeader> files = dao.getDeletedFiles(userId);
1305 for (final FileHeader f : files)
1306 result.add(f.getDTO());
1311 public void removeFileFromTrash(Long userId, Long fileId)
1312 throws ObjectNotFoundException, InsufficientPermissionsException {
1314 throw new ObjectNotFoundException("No user specified");
1316 throw new ObjectNotFoundException("No file specified");
1318 // Do the actual work.
1319 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1320 Folder parent = file.getFolder();
1322 throw new ObjectNotFoundException("The specified file has no parent folder");
1323 User user = dao.getEntityById(User.class, userId);
1324 if (!file.hasDeletePermission(user))
1325 throw new InsufficientPermissionsException("User " + user.getUsername() +
1326 " cannot restore file " + file.getName());
1328 file.setDeleted(false);
1330 touchParentFolders(parent, user, new Date());
1334 public void moveFolderToTrash(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
1336 throw new ObjectNotFoundException("No user specified");
1337 if (folderId == null)
1338 throw new ObjectNotFoundException("No folder specified");
1339 Folder folder = dao.getEntityById(Folder.class, folderId);
1340 User user = dao.getEntityById(User.class, userId);
1341 if (!folder.hasDeletePermission(user))
1342 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1343 folder.setDeleted(true);
1345 touchParentFolders(folder, user, new Date());
1346 for (FileHeader file : folder.getFiles())
1347 moveFileToTrash(userId, file.getId());
1348 for (Folder subFolder : folder.getSubfolders())
1349 moveFolderToTrash(userId, subFolder.getId());
1354 public void removeFolderFromTrash(Long userId, Long folderId)
1355 throws ObjectNotFoundException, InsufficientPermissionsException {
1357 throw new ObjectNotFoundException("No user specified");
1358 if (folderId == null)
1359 throw new ObjectNotFoundException("No folder specified");
1360 Folder folder = dao.getEntityById(Folder.class, folderId);
1361 User user = dao.getEntityById(User.class, userId);
1362 if (!folder.hasDeletePermission(user))
1363 throw new InsufficientPermissionsException("User " + user.getUsername() +
1364 " cannot restore folder " + folder.getName());
1365 folder.setDeleted(false);
1366 for (FileHeader file : folder.getFiles())
1367 removeFileFromTrash(userId, file.getId());
1368 for (Folder subFolder : folder.getSubfolders())
1369 removeFolderFromTrash(userId, subFolder.getId());
1371 touchParentFolders(folder, user, new Date());
1375 public List<FolderDTO> getDeletedRootFolders(Long userId) throws ObjectNotFoundException {
1376 List<Folder> folders = dao.getDeletedRootFolders(userId);
1377 List<FolderDTO> result = new ArrayList<FolderDTO>();
1378 for (Folder folder : folders)
1379 result.add(folder.getDTO());
1384 public void emptyTrash(Long userId) throws ObjectNotFoundException, InsufficientPermissionsException {
1385 List<FolderDTO> deletedRootFolders = getDeletedRootFolders(userId);
1386 for (FolderDTO fdto : deletedRootFolders)
1387 deleteFolder(userId, fdto.getId());
1388 List<FileHeaderDTO> deletedFiles = getDeletedFiles(userId);
1389 for (FileHeaderDTO filedto : deletedFiles)
1390 deleteFile(userId, filedto.getId());
1394 public void restoreTrash(Long userId) throws ObjectNotFoundException, InsufficientPermissionsException {
1395 List<FolderDTO> deletedRootFolders = getDeletedRootFolders(userId);
1396 for (FolderDTO fdto : deletedRootFolders)
1397 removeFolderFromTrash(userId, fdto.getId());
1398 List<FileHeaderDTO> deletedFiles = getDeletedFiles(userId);
1399 for (FileHeaderDTO filedto : deletedFiles)
1400 removeFileFromTrash(userId, filedto.getId());
1404 public User createUser(String username, String name, String mail,
1405 String idp, String idpid) throws ObjectNotFoundException {
1406 if (username == null)
1407 throw new ObjectNotFoundException("No username specified");
1409 throw new ObjectNotFoundException("No name specified");
1411 User user = new User();
1412 user.setUsername(username);
1414 user.setEmail(mail);
1415 user.setIdentityProvider(idp);
1416 user.setIdentityProviderId(idpid);
1417 Date now = new Date();
1418 AuditInfo auditInfo = new AuditInfo();
1419 auditInfo.setCreationDate(now);
1420 auditInfo.setModificationDate(now);
1421 user.setAuditInfo(auditInfo);
1422 user.setActive(true);
1423 user.generateAuthToken();
1424 user.generateWebDAVPassword();
1425 user.setUserClass(getDefaultUserClass());
1427 // Make sure we get an ID in the user object.
1429 // Create the root folder for the user.
1430 createFolder(user.getName(), null, user);
1435 * Get the default user class, which is the one with the lowest quota.
1437 private UserClass getDefaultUserClass() {
1438 return getUserClasses().get(0);
1442 public List<UserClass> getUserClasses() {
1443 List<UserClass> classes = dao.getUserClasses();
1444 // Create a default user class for first-time use. Afterwards, the
1445 // admin should modify or add to the userclass table.
1446 if (classes.size() == 0) {
1447 UserClass defaultClass = new UserClass();
1448 defaultClass.setName("default");
1449 Long defaultQuota = getConfiguration().getLong("quota", new Long(52428800L));
1450 defaultClass.setQuota(defaultQuota);
1451 dao.create(defaultClass);
1452 classes.add(defaultClass);
1458 public User findUserByEmail(String email) {
1459 return dao.findUserByEmail(email);
1463 public void updateUser(User user) {
1468 public User findUser(String username) {
1469 if (username == null)
1471 return dao.findUser(username);
1475 public User updateUserToken(Long userId) throws ObjectNotFoundException {
1477 throw new ObjectNotFoundException("No user specified");
1478 User user = dao.getEntityById(User.class, userId);
1479 user.generateAuthToken();
1484 public Set<PermissionDTO> getFolderPermissions(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
1486 throw new ObjectNotFoundException("No user specified");
1487 if (folderId == null)
1488 throw new ObjectNotFoundException("No folder specified");
1489 User user = dao.getEntityById(User.class, userId);
1490 Folder folder = dao.getEntityById(Folder.class, folderId);
1491 if(!folder.hasReadPermission(user))
1492 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1493 Set<Permission> perms = folder.getPermissions();
1494 Set<PermissionDTO> result = new LinkedHashSet<PermissionDTO>();
1495 for (Permission perm : perms)
1496 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId()))
1497 result.add(perm.getDTO());
1498 for (Permission perm : perms)
1499 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId())) {
1501 result.add(perm.getDTO());
1507 * Set the provided permissions as the new permissions of the specified
1512 * @param permissions
1513 * @throws ObjectNotFoundException
1514 * @throws InsufficientPermissionsException
1516 private void setFolderPermissions(User user, Folder folder, Set<PermissionDTO> permissions) throws ObjectNotFoundException, InsufficientPermissionsException {
1517 if (permissions != null && !permissions.isEmpty()) {
1518 User owner = folder.getOwner();
1519 PermissionDTO ownerPerm = null;
1520 for (PermissionDTO dto : permissions)
1521 if (dto.getUser() != null && dto.getUser().getId().equals(owner.getId())) {
1525 if (ownerPerm == null || !ownerPerm.hasRead() || !ownerPerm.hasWrite() || !ownerPerm.hasModifyACL())
1526 throw new InsufficientPermissionsException("Can't remove permissions from owner");
1527 // Delete previous entries
1528 for (Permission perm: folder.getPermissions())
1530 folder.getPermissions().clear();
1531 for (PermissionDTO dto : permissions) {
1532 // Skip 'empty' permission entries.
1533 if (!dto.getRead() && !dto.getWrite() && !dto.getModifyACL()) continue;
1534 folder.addPermission(getPermission(dto));
1537 for (FileHeader file : folder.getFiles()) {
1538 setFilePermissions(file, permissions);
1539 Date now = new Date();
1540 file.getAuditInfo().setModificationDate(now);
1541 file.getAuditInfo().setModifiedBy(user);
1543 for (Folder sub : folder.getSubfolders())
1544 setFolderPermissions(user, sub, permissions);
1548 private Permission getPermission(PermissionDTO dto) throws ObjectNotFoundException {
1549 Permission res = new Permission();
1550 if (dto.getGroup() != null)
1551 res.setGroup(dao.getEntityById(Group.class, dto.getGroup().getId()));
1552 else if (dto.getUser() != null)
1553 if (dto.getUser().getId() == null)
1554 res.setUser(dao.getUser(dto.getUser().getUsername()));
1556 res.setUser(dao.getEntityById(User.class, dto.getUser().getId()));
1557 res.setRead(dto.hasRead());
1558 res.setWrite(dto.hasWrite());
1559 res.setModifyACL(dto.hasModifyACL());
1564 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsersByUserNameLike(java.lang.String)
1567 public List<UserDTO> getUsersByUserNameLike(String username) {
1568 List<User> users = dao.getUsersByUserNameLike(username);
1569 List<UserDTO> result = new ArrayList<UserDTO>();
1570 for (User u : users)
1571 result.add(u.getDTO());
1577 public void addUserToGroup(Long userId, Long groupId, Long userToAddId) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
1579 throw new ObjectNotFoundException("No user specified");
1580 if (groupId == null)
1581 throw new ObjectNotFoundException("No group specified");
1582 if (userToAddId == null)
1583 throw new ObjectNotFoundException("No user to add specified");
1584 User user = dao.getEntityById(User.class, userId);
1585 Group group = dao.getEntityById(Group.class, groupId);
1586 if (!group.getOwner().equals(user))
1587 throw new InsufficientPermissionsException();
1588 User userToAdd = dao.getEntityById(User.class, userToAddId);
1589 if (group.contains(userToAdd))
1590 throw new DuplicateNameException("User already exists in group");
1591 group.getMembers().add(userToAdd);
1597 public void invalidateUserToken(Long userId) throws ObjectNotFoundException {
1599 throw new ObjectNotFoundException("No user specified");
1600 User user = dao.getEntityById(User.class, userId);
1601 user.invalidateAuthToken();
1606 public List<FolderDTO> getSharedRootFolders(Long userId) throws ObjectNotFoundException {
1608 throw new ObjectNotFoundException("No user specified");
1609 List<Folder> folders = dao.getSharedRootFolders(userId);
1610 List<FolderDTO> result = new ArrayList<FolderDTO>();
1611 for (Folder f : folders) {
1612 FolderDTO dto = f.getDTO();
1613 dto.setSubfolders(getSharedSubfolders(userId, f.getId()));
1620 public void removeMemberFromGroup(Long userId, Long groupId, Long memberId) throws ObjectNotFoundException, InsufficientPermissionsException {
1622 throw new ObjectNotFoundException("No user specified");
1623 if (groupId == null)
1624 throw new ObjectNotFoundException("No group specified");
1625 if (memberId == null)
1626 throw new ObjectNotFoundException("No member specified");
1627 User owner = dao.getEntityById(User.class, userId);
1628 Group group = dao.getEntityById(Group.class, groupId);
1629 User member = dao.getEntityById(User.class, memberId);
1630 if (!group.getOwner().equals(owner))
1631 throw new InsufficientPermissionsException("User is not the owner of the group");
1632 group.removeMemberFromGroup(member);
1638 public List<UserDTO> getUsersSharingFoldersForUser(Long userId) throws ObjectNotFoundException {
1639 List<User> users = dao.getUsersSharingFoldersForUser(userId);
1640 List<User> usersFiles = dao.getUsersSharingFilesForUser(userId);
1641 List<UserDTO> res = new ArrayList<UserDTO>();
1642 for (User u : users)
1643 res.add(u.getDTO());
1644 for(User fu : usersFiles)
1645 if(!users.contains(fu))
1646 res.add(fu.getDTO());
1651 public Set<PermissionDTO> getFilePermissions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1653 throw new ObjectNotFoundException("No user specified");
1655 throw new ObjectNotFoundException("No folder specified");
1656 User user = dao.getEntityById(User.class, userId);
1657 FileHeader folder = dao.getEntityById(FileHeader.class, fileId);
1658 if(!folder.hasReadPermission(user))
1659 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1660 Set<Permission> perms = folder.getPermissions();
1661 Set<PermissionDTO> result = new LinkedHashSet<PermissionDTO>();
1662 for (Permission perm : perms)
1663 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId()))
1664 result.add(perm.getDTO());
1665 for (Permission perm : perms)
1666 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId())) {
1668 result.add(perm.getDTO());
1673 * Set the provided permissions as the new permissions of the specified
1674 * file. This method sets the modification date/user attributes to the
1675 * current values as a side effect.
1678 * @param permissions
1679 * @throws ObjectNotFoundException
1680 * @throws InsufficientPermissionsException
1682 private void setFilePermissions(FileHeader file,
1683 Set<PermissionDTO> permissions)
1684 throws ObjectNotFoundException, InsufficientPermissionsException {
1685 if (permissions != null && !permissions.isEmpty()) {
1686 PermissionDTO ownerPerm = null;
1687 for (PermissionDTO dto : permissions)
1688 if (dto.getUser() != null && dto.getUser().getId().equals(file.getOwner().getId())) {
1692 if (ownerPerm == null || !ownerPerm.hasRead() || !ownerPerm.hasWrite() || !ownerPerm.hasModifyACL())
1693 throw new InsufficientPermissionsException("Can't remove permissions from owner");
1694 // Delete previous entries.
1695 for (Permission perm: file.getPermissions())
1697 file.getPermissions().clear();
1698 for (PermissionDTO dto : permissions) {
1699 // Skip 'empty' permission entries.
1700 if (!dto.getRead() && !dto.getWrite() && !dto.getModifyACL()) continue;
1701 file.addPermission(getPermission(dto));
1708 public List<FileHeaderDTO> getSharedFilesNotInSharedFolders(Long userId) throws ObjectNotFoundException {
1710 throw new ObjectNotFoundException("No user specified");
1711 List<FileHeader> files = dao.getSharedFilesNotInSharedFolders(userId);
1712 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1713 for (FileHeader f : files)
1714 result.add(f.getDTO());
1719 public List<FileHeaderDTO> getSharedFiles(Long userId) throws ObjectNotFoundException {
1721 throw new ObjectNotFoundException("No user specified");
1722 List<FileHeader> files = dao.getSharedFiles(userId);
1723 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1724 for (FileHeader f : files)
1725 result.add(f.getDTO());
1730 public List<FolderDTO> getSharedFolders(Long userId) throws ObjectNotFoundException {
1732 throw new ObjectNotFoundException("No user specified");
1733 List<Folder> folders = dao.getSharedFolders(userId);
1734 List<FolderDTO> result = new ArrayList<FolderDTO>();
1735 for (Folder f : folders)
1736 result.add(f.getDTO());
1741 public List<FileHeaderDTO> getSharedFiles(Long ownerId, Long callingUserId) throws ObjectNotFoundException {
1742 if (ownerId == null)
1743 throw new ObjectNotFoundException("No owner specified");
1744 if (callingUserId == null)
1745 throw new ObjectNotFoundException("No calling user specified");
1746 List<FileHeader> folders = dao.getSharedFiles(ownerId, callingUserId);
1747 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1748 for (FileHeader f : folders)
1749 result.add(f.getDTO());
1754 public List<FolderDTO> getSharedRootFolders(Long ownerId, Long callingUserId) throws ObjectNotFoundException {
1755 if (ownerId == null)
1756 throw new ObjectNotFoundException("No owner specified");
1757 if (callingUserId == null)
1758 throw new ObjectNotFoundException("No calling user specified");
1759 List<Folder> folders = dao.getSharedRootFolders(ownerId, callingUserId);
1760 List<FolderDTO> result = new ArrayList<FolderDTO>();
1761 for (Folder f : folders) {
1762 FolderDTO dto = f.getDTO();
1763 dto.setSubfolders(getSharedSubfolders(ownerId, callingUserId, f.getId()));
1771 public List<FolderDTO> getSharedSubfolders(Long userId, Long folderId) throws ObjectNotFoundException {
1773 throw new ObjectNotFoundException("No user specified");
1774 if (folderId == null)
1775 throw new ObjectNotFoundException("No folder specified");
1776 User user = dao.getEntityById(User.class, userId);
1777 Folder folder = dao.getEntityById(Folder.class, folderId);
1778 List<FolderDTO> result = new ArrayList<FolderDTO>();
1779 if (folder.isShared(user) || folder.isReadForAll())
1780 for (Folder f : folder.getSubfolders())
1781 if ((f.isShared(user) || f.isReadForAll()) && !f.isDeleted())
1782 result.add(f.getDTO());
1787 public List<FolderDTO> getSharedSubfolders(Long userId, Long callingUserId, Long folderId) throws ObjectNotFoundException {
1789 throw new ObjectNotFoundException("No user specified");
1790 if (callingUserId == null)
1791 throw new ObjectNotFoundException("No user specified");
1792 if (folderId == null)
1793 throw new ObjectNotFoundException("No folder specified");
1794 User user = dao.getEntityById(User.class, callingUserId);
1795 Folder folder = dao.getEntityById(Folder.class, folderId);
1796 List<FolderDTO> result = new ArrayList<FolderDTO>();
1797 if (folder.isSharedForOtherUser(user))
1798 for (Folder f : folder.getSubfolders())
1799 if (f.isSharedForOtherUser(user) && !f.isDeleted()){
1800 FolderDTO dto = f.getDTO();
1801 dto.setSubfolders(getSharedSubfolders(userId, callingUserId, dto.getId()));
1809 public List<FileHeaderDTO> searchFiles(Long userId, String query) throws ObjectNotFoundException {
1811 throw new ObjectNotFoundException("No user specified");
1812 User user = getUser(userId);
1814 throw new ObjectNotFoundException("No query specified");
1815 List<FileHeader> files = search(user.getId(), query);
1816 List<FileHeaderDTO> res = new ArrayList<FileHeaderDTO>();
1817 for(FileHeader f : files)
1818 res.add(f.getDTO());
1823 * Performs the actuals search on the solr server and returns the results
1825 * We have to use the dismax query type (instead of the
1826 * standard) because it allows for search time field boosting. This is because we can't use indexing
1827 * time field boosting due to the patched rich indexing API that does not allow it
1831 * @return a List of FileHeader objects
1833 private List<FileHeader> search(Long userId, String query) {
1835 HttpClient httpClient = new HttpClient();
1837 GetMethod method = new GetMethod(getConfiguration().getString("solrSelectUrl"));
1838 NameValuePair[] params = {new NameValuePair("qt", "dismax"),
1839 new NameValuePair("q", query),
1840 new NameValuePair("sort", "score desc"),
1841 new NameValuePair("indent", "on")};
1842 method.setQueryString(params);
1845 String response = null;
1847 statusCode = httpClient.executeMethod(method);
1848 logger.debug("HTTP status: " + statusCode);
1849 response = method.getResponseBodyAsString();
1850 logger.debug(response);
1852 if (statusCode != 200 && retryCount < 3)
1854 Thread.sleep(3000); //Give Solr a little time to be available
1855 } catch (InterruptedException e) {
1857 } while (statusCode != 200 && retryCount < 3);
1858 if (statusCode != 200)
1859 throw new EJBException("Search query return error:\n" + response);
1861 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
1862 DocumentBuilder db = dbf.newDocumentBuilder();
1863 Document doc = db.parse(method.getResponseBodyAsStream());
1864 method.releaseConnection();
1866 Node root = doc.getElementsByTagName("response").item(0);
1867 Node lst = root.getFirstChild().getNextSibling();
1868 Node status = lst.getFirstChild().getNextSibling();
1869 if (status.getAttributes().getNamedItem("name").getNodeValue().equals("status") &&
1870 status.getTextContent().equals("0")) {
1871 List<FileHeader> fileResult = new ArrayList<FileHeader>();
1872 Node result = lst.getNextSibling().getNextSibling();
1873 NodeList docs = result.getChildNodes();
1874 User user = getUser(userId);
1875 for (int i=1; i<docs.getLength(); i=i+2) {
1876 Node d = docs.item(i);
1877 NodeList docData = d.getChildNodes();
1878 for (int j=1; j<docData.getLength(); j=j+2) {
1879 Node dd = docData.item(j);
1880 if (dd.getAttributes().item(0).getNodeName().equals("name") &&
1881 dd.getAttributes().item(0).getNodeValue().equals("id")) {
1882 Long fileId = Long.valueOf(dd.getTextContent());
1884 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1885 if (file.hasReadPermission(user)) {
1886 fileResult.add(file);
1887 logger.debug("File added " + fileId);
1889 } catch (ObjectNotFoundException e) {
1890 logger.warn("Search result not found", e);
1897 throw new EJBException();
1898 } catch (HttpException e) {
1899 throw new EJBException(e);
1900 } catch (IOException e) {
1901 throw new EJBException(e);
1902 } catch (SAXException e) {
1903 throw new EJBException(e);
1904 } catch (ParserConfigurationException e) {
1905 throw new EJBException(e);
1906 } catch (ObjectNotFoundException e) {
1907 throw new EJBException(e);
1912 public void copyFiles(Long userId, List<Long> fileIds, Long destId) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
1913 for(Long l : fileIds){
1914 FileHeader file = dao.getEntityById(FileHeader.class, l);
1915 copyFile(userId, l, destId, file.getName());
1922 public void moveFiles(Long userId, List<Long> fileIds, Long destId) throws InsufficientPermissionsException, ObjectNotFoundException, QuotaExceededException {
1923 for(Long l : fileIds){
1924 FileHeader file = dao.getEntityById(FileHeader.class, l);
1925 moveFile(userId, l, destId, file.getName());
1931 public void deleteFiles(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1933 throw new ObjectNotFoundException("No user specified");
1934 final User user = dao.getEntityById(User.class, userId);
1935 List<String> filesToRemove = new ArrayList<String>();
1936 //first delete database objects
1937 for(Long fileId : fileIds){
1939 throw new ObjectNotFoundException("No file specified");
1940 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1941 final Folder parent = file.getFolder();
1943 throw new ObjectNotFoundException("The specified file has no parent folder");
1944 if (!file.hasDeletePermission(user))
1945 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
1947 parent.removeFile(file);
1948 for (final FileBody body : file.getBodies())
1949 filesToRemove.add(body.getStoredFilePath());
1951 touchParentFolders(parent, user, new Date());
1953 //then remove physical files if everything is ok
1954 for(String physicalFileName : filesToRemove)
1955 deleteActualFile(physicalFileName);
1956 //then unindex deleted files
1957 for(Long fileId : fileIds)
1958 indexFile(fileId, true);
1963 public void moveFilesToTrash(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1964 for(Long l : fileIds)
1965 moveFileToTrash(userId, l);
1970 public void removeFilesFromTrash(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1971 for(Long l : fileIds)
1972 removeFileFromTrash(userId, l);
1977 public Nonce createNonce(Long userId) throws ObjectNotFoundException {
1979 throw new ObjectNotFoundException("No user specified");
1980 User user = dao.getEntityById(User.class, userId);
1981 Nonce nonce = Nonce.createNonce(user.getId());
1987 public Nonce getNonce(String nonce, Long userId) throws ObjectNotFoundException {
1989 throw new ObjectNotFoundException("No user specified");
1991 throw new ObjectNotFoundException("No nonce specified");
1992 return dao.getNonce(nonce, userId);
1996 public void removeNonce(Long id) throws ObjectNotFoundException {
1998 throw new ObjectNotFoundException("No nonce specified");
1999 Nonce nonce = dao.getEntityById(Nonce.class, id);
2004 public void activateUserNonce(Long userId, String nonce, Date nonceExpiryDate) throws ObjectNotFoundException {
2006 throw new ObjectNotFoundException("No user specified");
2007 User user = dao.getEntityById(User.class, userId);
2008 user.setNonce(nonce);
2009 user.setNonceExpiryDate(nonceExpiryDate);
2013 public StatsDTO getUserStatistics(Long userId) throws ObjectNotFoundException {
2015 throw new ObjectNotFoundException("No user specified");
2016 StatsDTO stats = new StatsDTO();
2017 stats.setFileCount(dao.getFileCount(userId));
2018 Long fileSize = dao.getFileSize(userId);
2019 stats.setFileSize(fileSize);
2020 Long quota = getQuota(userId);
2021 Long quotaLeft = quota - fileSize;
2022 stats.setQuotaLeftSize(quotaLeft);
2027 public List<FileBodyDTO> getVersions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
2029 throw new ObjectNotFoundException("No user specified");
2031 throw new ObjectNotFoundException("No file specified");
2032 User user = dao.getEntityById(User.class, userId);
2033 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
2034 if(!header.hasReadPermission(user))
2035 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2036 List<FileBodyDTO> result = new LinkedList<FileBodyDTO>();
2037 for(int i = header.getBodies().size()-1 ; i>=0; i--)
2038 result.add(header.getBodies().get(i).getDTO());
2043 public void removeVersion(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
2045 throw new ObjectNotFoundException("No user specified");
2047 throw new ObjectNotFoundException("No file specified");
2049 throw new ObjectNotFoundException("No body specified");
2050 User user = dao.getEntityById(User.class, userId);
2051 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
2052 if(!header.hasWritePermission(user))
2053 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2054 FileBody body = dao.getEntityById(FileBody.class, bodyId);
2055 if(body.equals(header.getCurrentBody())){
2057 if(header.getBodies().size() == 1)
2058 throw new InsufficientPermissionsException("You cant delete this version, Delete file instead!");
2059 for(FileBody b : header.getBodies())
2060 if(b.getVersion() == body.getVersion()-1)
2061 header.setCurrentBody(b);
2063 deleteActualFile(body.getStoredFilePath());
2064 header.getBodies().remove(body);
2066 Folder parent = header.getFolder();
2067 touchParentFolders(parent, user, new Date());
2072 public void restoreVersion(Long userId, Long fileId, int version) throws ObjectNotFoundException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
2074 throw new ObjectNotFoundException("No user specified");
2076 throw new ObjectNotFoundException("No file specified");
2077 User user = dao.getEntityById(User.class, userId);
2078 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
2079 if(!header.hasWritePermission(user))
2080 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2081 FileBody body = dao.getFileVersion(fileId, version);
2082 final File fileContents = new File(body.getStoredFilePath());
2085 updateFileContents(userId, fileId, body.getMimeType(), new FileInputStream(fileContents) );
2086 } catch (FileNotFoundException e) {
2087 throw new GSSIOException(e);
2093 * @see gr.ebs.gss.server.ejb.ExternalAPI#removeOldVersions(java.lang.Long, java.lang.Long)
2096 public void removeOldVersions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
2098 throw new ObjectNotFoundException("No user specified");
2100 throw new ObjectNotFoundException("No file specified");
2101 User user = dao.getEntityById(User.class, userId);
2102 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
2103 if(!header.hasWritePermission(user))
2104 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2105 Iterator<FileBody> it = header.getBodies().iterator();
2106 while(it.hasNext()){
2107 FileBody body = it.next();
2108 if(!body.equals(header.getCurrentBody())){
2109 deleteActualFile(body.getStoredFilePath());
2114 header.getCurrentBody().setVersion(1);
2116 Folder parent = header.getFolder();
2117 touchParentFolders(parent, user, new Date());
2121 * Gets the quota left for specified user ID.
2123 private Long getQuotaLeft(Long userId) throws ObjectNotFoundException{
2124 Long fileSize = dao.getFileSize(userId);
2125 Long quota = getQuota(userId);
2126 return quota - fileSize;
2130 * Gets the quota for specified user ID.
2132 private Long getQuota(Long userId) throws ObjectNotFoundException{
2133 UserClass uc = getUser(userId).getUserClass();
2135 uc = getDefaultUserClass();
2136 return uc.getQuota();
2140 public void rebuildSolrIndex() {
2142 CommonsHttpSolrServer solr = new CommonsHttpSolrServer(getConfiguration().getString("solr.url"));
2143 solr.deleteByQuery("*:*");
2146 List<Long> fileIds = dao.getAllFileIds();
2147 for (Long id : fileIds) {
2152 } catch (IOException e) {
2153 throw new EJBException(e);
2154 } catch (SolrServerException e) {
2155 throw new EJBException(e);
2160 * Sends a optimize message to the solr server
2163 * @param retryCount If the commit fails, it is retried three times. This parameter is passed in the recursive
2164 * calls to stop the recursion
2165 * @throws UnsupportedEncodingException
2166 * @throws IOException
2167 * @throws HttpException
2169 private void sendOptimize(HttpClient httpClient, int retryCount) throws UnsupportedEncodingException, IOException, HttpException {
2170 PostMethod method = null;
2172 logger.debug("Optimize retry: " + retryCount);
2173 method = new PostMethod(getConfiguration().getString("solrUpdateUrl"));
2174 method.setRequestEntity(new StringRequestEntity("<optimize/>", "text/xml", "iso8859-1"));
2175 int statusCode = httpClient.executeMethod(method);
2176 logger.debug("HTTP status: " + statusCode);
2177 String response = method.getResponseBodyAsString();
2178 logger.debug(response);
2179 if (statusCode != 200 && retryCount < 2) {
2181 Thread.sleep(10000); //Give Solr a little time to be available
2182 } catch (InterruptedException e) {
2184 sendOptimize(httpClient, retryCount + 1);
2189 method.releaseConnection();
2194 public FileHeaderDTO createFile(Long userId, Long folderId, String name, String mimeType, long fileSize, String filePath)
2195 throws DuplicateNameException, ObjectNotFoundException, GSSIOException,
2196 InsufficientPermissionsException, QuotaExceededException {
2199 throw new ObjectNotFoundException("No user specified");
2200 if (folderId == null)
2201 throw new ObjectNotFoundException("No folder specified");
2202 String contentType = mimeType;
2203 if (StringUtils.isEmpty(mimeType))
2204 contentType = DEFAULT_MIME_TYPE;
2205 if (StringUtils.isEmpty(name))
2206 throw new ObjectNotFoundException("No file name specified");
2207 if (dao.existsFolderOrFile(folderId, name))
2208 throw new DuplicateNameException("A folder or file with the name '" + name +
2209 "' already exists at this level");
2211 // Do the actual work.
2212 Folder parent = null;
2214 parent = dao.getEntityById(Folder.class, folderId);
2215 } catch (final ObjectNotFoundException onfe) {
2216 // Supply a more accurate problem description.
2217 throw new ObjectNotFoundException("Parent folder not found");
2219 final User owner = dao.getEntityById(User.class, userId);
2220 if (!parent.hasWritePermission(owner))
2221 throw new InsufficientPermissionsException("You don't have the permissions to write to this folder");
2222 final FileHeader file = new FileHeader();
2224 parent.addFile(file);
2225 // set file owner to folder owner
2226 file.setOwner(parent.getOwner());
2227 //set file's readForAll value according to parent folder readForAll value
2228 file.setReadForAll(parent.isReadForAll());
2230 final Date now = new Date();
2231 final AuditInfo auditInfo = new AuditInfo();
2232 auditInfo.setCreatedBy(owner);
2233 auditInfo.setCreationDate(now);
2234 auditInfo.setModifiedBy(owner);
2235 auditInfo.setModificationDate(now);
2236 file.setAuditInfo(auditInfo);
2237 // TODO set the proper versioning flag on creation
2238 file.setVersioned(false);
2240 for (final Permission p : parent.getPermissions()) {
2241 final Permission permission = new Permission();
2242 permission.setGroup(p.getGroup());
2243 permission.setUser(p.getUser());
2244 permission.setRead(p.getRead());
2245 permission.setWrite(p.getWrite());
2246 permission.setModifyACL(p.getModifyACL());
2247 file.addPermission(permission);
2250 // Create the file body.
2252 createFileBody(name, contentType, fileSize, filePath, file, auditInfo);
2253 } catch (FileNotFoundException e) {
2254 throw new GSSIOException(e);
2256 touchParentFolders(parent, owner, new Date());
2258 indexFile(file.getId(), false);
2260 return file.getDTO();
2264 public FileHeaderDTO updateFileContents(Long userId, Long fileId, String mimeType, long fileSize, String filePath) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
2266 throw new ObjectNotFoundException("No user specified");
2268 throw new ObjectNotFoundException("No file specified");
2269 String contentType = mimeType;
2271 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
2273 // if no mime type or the generic mime type is defined by the client, then try to identify it from the filename extension
2274 if (StringUtils.isEmpty(mimeType) || "application/octet-stream".equals(mimeType)
2275 || "application/download".equals(mimeType) || "application/force-download".equals(mimeType)
2276 || "octet/stream".equals(mimeType) || "application/unknown".equals(mimeType))
2277 contentType = identifyMimeType(file.getName());
2279 final User owner = dao.getEntityById(User.class, userId);
2280 if (!file.hasWritePermission(owner))
2281 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2282 final Date now = new Date();
2283 final AuditInfo auditInfo = new AuditInfo();
2284 auditInfo.setCreatedBy(owner);
2285 auditInfo.setCreationDate(now);
2286 auditInfo.setModifiedBy(owner);
2287 auditInfo.setModificationDate(now);
2289 createFileBody(file.getName(), contentType, fileSize, filePath, file, auditInfo);
2290 } catch (FileNotFoundException e) {
2291 throw new GSSIOException(e);
2293 Folder parent = file.getFolder();
2294 touchParentFolders(parent, owner, new Date());
2296 indexFile(fileId, false);
2297 return file.getDTO();
2301 * Helper method for identifying mime type by examining the filename extension
2304 * @return the mime type
2306 private String identifyMimeType(String filename) {
2307 if (filename.indexOf('.') != -1) {
2308 String extension = filename.substring(filename.lastIndexOf('.')).toLowerCase(Locale.ENGLISH);
2309 if (".doc".equals(extension))
2310 return "application/msword";
2311 else if (".xls".equals(extension))
2312 return "application/vnd.ms-excel";
2313 else if (".ppt".equals(extension))
2314 return "application/vnd.ms-powerpoint";
2315 else if (".pdf".equals(extension))
2316 return "application/pdf";
2317 else if (".gif".equals(extension))
2319 else if (".jpg".equals(extension) || ".jpeg".equals(extension) || ".jpe".equals(extension))
2320 return "image/jpeg";
2321 else if (".tiff".equals(extension) || ".tif".equals(extension))
2322 return "image/tiff";
2323 else if (".png".equals(extension))
2325 else if (".bmp".equals(extension))
2328 // when all else fails assign the default mime type
2329 return DEFAULT_MIME_TYPE;
2333 * Helper method to create a new file body and attach it as the current body
2334 * of the provided file header.
2336 * @param name the original file name
2337 * @param mimeType the content type
2338 * @param fileSize the uploaded file size
2339 * @param filePath the uploaded file full path
2340 * @param header the file header that will be associated with the new body
2341 * @param auditInfo the audit info
2342 * @param owner the owner of the file
2343 * @throws FileNotFoundException
2344 * @throws QuotaExceededException
2345 * @throws ObjectNotFoundException if the owner was not found
2347 private void createFileBody(String name, String mimeType, long fileSize, String filePath,
2348 FileHeader header, AuditInfo auditInfo)
2349 throws FileNotFoundException, QuotaExceededException, ObjectNotFoundException {
2351 long currentTotalSize = 0;
2352 if (!header.isVersioned() && header.getCurrentBody() != null && header.getBodies() != null)
2353 currentTotalSize = header.getTotalSize();
2354 Long quotaLeft = getQuotaLeft(header.getOwner().getId());
2355 if(quotaLeft < fileSize-currentTotalSize) {
2356 // quota exceeded -> delete the file
2357 deleteActualFile(filePath);
2358 throw new QuotaExceededException("Not enough free space available");
2361 FileBody body = new FileBody();
2363 // if no mime type or the generic mime type is defined by the client, then try to identify it from the filename extension
2364 if (StringUtils.isEmpty(mimeType) || "application/octet-stream".equals(mimeType)
2365 || "application/download".equals(mimeType) || "application/force-download".equals(mimeType)
2366 || "octet/stream".equals(mimeType) || "application/unknown".equals(mimeType))
2367 body.setMimeType(identifyMimeType(name));
2369 body.setMimeType(mimeType);
2370 body.setAuditInfo(auditInfo);
2371 body.setFileSize(fileSize);
2372 body.setOriginalFilename(name);
2373 body.setStoredFilePath(filePath);
2374 //CLEAR OLD VERSION IF FILE IS NOT VERSIONED AND GETS UPDATED
2375 if(!header.isVersioned() && header.getCurrentBody() != null){
2376 header.setCurrentBody(null);
2377 if (header.getBodies() != null) {
2378 Iterator<FileBody> it = header.getBodies().iterator();
2379 while(it.hasNext()){
2380 FileBody bo = it.next();
2381 deleteActualFile(bo.getStoredFilePath());
2389 header.addBody(body);
2390 header.setAuditInfo(auditInfo);
2397 @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
2398 public File uploadFile(InputStream stream, Long userId) throws IOException, ObjectNotFoundException {
2400 throw new ObjectNotFoundException("No user specified");
2401 User owner = dao.getEntityById(User.class, userId);
2403 throw new ObjectNotFoundException("No user specified");
2404 long start = 0, end = 0;
2405 if (logger.isDebugEnabled())
2406 start = System.currentTimeMillis();
2407 File result = new File(generateRepositoryFilePath());
2409 final FileOutputStream output = new FileOutputStream(result);
2410 final byte[] buffer = new byte[UPLOAD_BUFFER_SIZE];
2413 while (-1 != (n = stream.read(buffer)))
2414 output.write(buffer, 0, n);
2417 } catch (IOException e) {
2418 if (!result.delete())
2419 logger.warn("Could not delete " + result.getPath());
2422 if (logger.isDebugEnabled()) {
2423 end = System.currentTimeMillis();
2424 logger.debug("Time to upload: " + (end - start) + " (msec)");
2431 public void createFileUploadProgress(Long userId, String filename, Long bytesTransfered, Long fileSize) throws ObjectNotFoundException{
2434 throw new ObjectNotFoundException("No user specified");
2435 User user = dao.getEntityById(User.class, userId);
2436 FileUploadStatus status = dao.getFileUploadStatus(userId, filename);
2438 status = new FileUploadStatus();
2439 status.setOwner(user);
2440 status.setFilename(filename);
2441 status.setBytesUploaded(bytesTransfered);
2442 status.setFileSize(fileSize);
2446 status.setBytesUploaded(bytesTransfered);
2447 status.setFileSize(fileSize);
2454 public void removeFileUploadProgress(Long userId, String filename) throws ObjectNotFoundException{
2456 throw new ObjectNotFoundException("No user specified");
2457 FileUploadStatus status = dao.getFileUploadStatus(userId, filename);
2463 public FileUploadStatus getFileUploadStatus(Long userId, String fileName) {
2464 return dao.getFileUploadStatus(userId, fileName);
2468 public FolderDTO getFolderWithSubfolders(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
2470 throw new ObjectNotFoundException("No user specified");
2471 if (folderId == null)
2472 throw new ObjectNotFoundException("No folder specified");
2473 final User user = dao.getEntityById(User.class, userId);
2474 final Folder folder = dao.getEntityById(Folder.class, folderId);
2475 // Check permissions
2476 if (!folder.hasReadPermission(user))
2477 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
2478 List<FolderDTO> subfolders = new ArrayList<FolderDTO>();
2479 if (folder.hasReadPermission(user))
2480 for (Folder f : folder.getSubfolders())
2481 if (f.hasReadPermission(user) && !f.isDeleted())
2482 subfolders.add(f.getDTO());
2483 FolderDTO result = folder.getDTO();
2484 result.setSubfolders(subfolders);
2485 return folder.getDTO();
2489 public FolderDTO getFolderWithSubfolders(Long userId, Long callingUserId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
2491 throw new ObjectNotFoundException("No user specified");
2492 if (folderId == null)
2493 throw new ObjectNotFoundException("No folder specified");
2494 User user = dao.getEntityById(User.class, callingUserId);
2495 Folder folder = dao.getEntityById(Folder.class, folderId);
2496 // Check permissions
2497 if (!folder.hasReadPermission(user))
2498 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
2500 FolderDTO result = folder.getDTO();
2501 result.setSubfolders(getSharedSubfolders(userId, callingUserId, folder.getId()));
2506 public FileBodyDTO getFileVersion(Long userId, Long fileId, int version)
2507 throws ObjectNotFoundException, InsufficientPermissionsException {
2509 throw new ObjectNotFoundException("No user specified");
2511 throw new ObjectNotFoundException("No file specified");
2513 throw new ObjectNotFoundException("No valid version specified");
2514 User user = dao.getEntityById(User.class, userId);
2515 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
2516 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
2517 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2518 FileBody body = dao.getFileVersion(fileId, version);
2519 return body.getDTO();
2523 public User updateUserPolicyAcceptance(Long userId, boolean isAccepted) throws ObjectNotFoundException {
2525 throw new ObjectNotFoundException("No user specified");
2526 User user = dao.getEntityById(User.class, userId);
2527 user.setAcceptedPolicy(isAccepted);
2532 public void updateAccounting(User user, Date date, long bandwidthDiff) {
2533 dao.updateAccounting(user, date, bandwidthDiff);
2537 public boolean canReadFolder(Long userId, Long folderId) throws ObjectNotFoundException {
2539 throw new ObjectNotFoundException("No user specified");
2540 if (folderId == null)
2541 throw new ObjectNotFoundException("No folder specified");
2542 User user = dao.getEntityById(User.class, userId);
2543 Folder folder = dao.getEntityById(Folder.class, folderId);
2544 // Check permissions
2545 if (!folder.hasReadPermission(user))
2551 public String resetWebDAVPassword(Long userId) throws ObjectNotFoundException {
2553 throw new ObjectNotFoundException("No user specified");
2554 User user = dao.getEntityById(User.class, userId);
2555 user.generateWebDAVPassword();
2556 return user.getWebDAVPassword();
2560 public Invitation findInvite(String code) {
2563 return dao.findInvite(code);
2567 public void createLdapUser(String username, String firstname, String lastname, String email, String password) {
2568 LDAPConnection lc = new LDAPConnection();
2569 LDAPAttributeSet attributeSet = new LDAPAttributeSet();
2570 attributeSet.add(new LDAPAttribute("objectClass", getConfiguration().getStringArray("objectClass")));
2571 attributeSet.add(new LDAPAttribute("uid", username));
2572 attributeSet.add(new LDAPAttribute("cn", new String[]{firstname + " " + lastname}));
2573 attributeSet.add(new LDAPAttribute("sn", lastname));
2574 attributeSet.add(new LDAPAttribute("givenName", firstname));
2575 attributeSet.add(new LDAPAttribute("mail", email));
2576 attributeSet.add(new LDAPAttribute("userPassword", password));
2577 String dn = "uid=" + username + "," + getConfiguration().getString("baseDn");
2578 LDAPEntry newEntry = new LDAPEntry(dn, attributeSet);
2580 lc.connect(getConfiguration().getString("ldapHost"), LDAPConnection.DEFAULT_PORT);
2581 lc.bind(LDAPConnection.LDAP_V3, getConfiguration().getString("bindDn"),
2582 getConfiguration().getString("bindPassword").getBytes("UTF8"));
2584 logger.info("Successfully added LDAP account: " + dn);
2586 } catch(LDAPException e) {
2587 throw new RuntimeException(e);
2588 } catch(UnsupportedEncodingException e) {
2589 throw new RuntimeException(e);
2595 public UserClass upgradeUserClass(String username, String code) throws ObjectNotFoundException, InvitationUsedException {
2596 User user = findUser(username);
2598 throw new ObjectNotFoundException("The user was not found");
2599 Invitation invite = findInvite(code);
2600 if (invite.getUser() != null)
2601 throw new InvitationUsedException("This code has already been used");
2602 invite.setUser(user);
2603 UserClass couponClass = getCouponUserClass();
2604 user.setUserClass(couponClass);
2609 public UserClass getCouponUserClass() {
2610 return dao.findCouponUserClass();
2614 * Mark the folder as modified from the specified user and change it's modification date.
2616 private void touchFolder(Folder f, User _user, Date now){
2617 final AuditInfo auditInfo = f.getAuditInfo();
2618 auditInfo.setModificationDate(now);
2619 auditInfo.setModifiedBy(_user);
2620 f.setAuditInfo(auditInfo);
2624 * Mark the file as modified from the specified user and change it's modification date.
2626 private void touchFile(FileHeader f, User _user, Date now){
2627 final AuditInfo auditInfo = f.getAuditInfo();
2628 auditInfo.setModificationDate(now);
2629 auditInfo.setModifiedBy(_user);
2630 f.setAuditInfo(auditInfo);
2634 * Set the provided readForAll as the new readforAll value of the specified
2635 * folder and sub-folders.
2640 * @throws ObjectNotFoundException
2643 private void setFolderReadForAll(User user, Folder folder, Boolean readForAll){
2644 if (readForAll != null && user.equals(folder.getOwner())){
2645 folder.setReadForAll(readForAll);
2647 for (FileHeader file : folder.getFiles())
2648 file.setReadForAll(readForAll);
2650 //only update subfolders when readforall is true. otherwise all sub-folders stay untouched
2651 for (Folder sub : folder.getSubfolders())
2652 setFolderReadForAll(user, sub, readForAll);
2661 * @throws ObjectNotFoundException
2662 * @throws SolrServerException
2663 * @throws IOException
2664 * @throws MalformedURLException
2666 public void postFileToSolr(Long id) {
2668 FileHeader file = dao.getEntityById(FileHeader.class, id);
2669 FileBody body = file.getCurrentBody();
2670 String mime = body.getMimeType();
2671 boolean multipart = true;
2672 if (!mime.equals("application/pdf")
2673 && !mime.equals("text/plain")
2674 && !mime.equals("text/html")
2675 && !mime.endsWith("msword")
2676 && !mime.endsWith("ms-excel")
2677 && !mime.endsWith("powerpoint")
2678 || (body.getFileSize() > getConfiguration().getLong("solrDocumentUploadLimitInKB") * 1024))
2682 sendMetaDataOnly(getConfiguration().getString("solr.url"), file);
2684 CommonsHttpSolrServer solr = new CommonsHttpSolrServer(getConfiguration().getString("solr.url"));
2685 ContentStreamUpdateRequest solrRequest = new ContentStreamUpdateRequest(getConfiguration().getString("solr.rich.update.path"));
2686 solrRequest.setParam("literal.id", file.getId().toString());
2687 solrRequest.setParam("literal.name", file.getName());
2688 for (FileTag t : file.getFileTags()) {
2689 solrRequest.getParams().add("literal.tag", t.getTag());
2691 solrRequest.addFile(new File(body.getStoredFilePath()));
2692 solrRequest.setAction(AbstractUpdateRequest.ACTION.COMMIT, true, true);
2694 solr.request(solrRequest);
2696 catch (SolrException e) {
2697 logger.warn("File " + id + " failed with " + e.getLocalizedMessage() + ". Retrying without the file");
2698 //Let 's try without the file
2699 sendMetaDataOnly(getConfiguration().getString("solr.url"), file);
2701 catch (NullPointerException e) {
2702 logger.warn("File " + id + " failed with " + e.getLocalizedMessage() + ". Retrying without the file");
2703 //Let 's try without the file
2704 sendMetaDataOnly(getConfiguration().getString("solr.url"), file);
2706 catch (SolrServerException e) {
2707 logger.warn("File " + id + " failed with " + e.getLocalizedMessage() + ". Retrying without the file");
2708 //Let 's try without the file
2709 sendMetaDataOnly(getConfiguration().getString("solr.url"), file);
2712 } catch (MalformedURLException e) {
2713 throw new EJBException(e);
2714 } catch (ObjectNotFoundException e) {
2715 logger.error("Indexing of file id " + id + " failed.", e);
2716 } catch (SolrServerException e) {
2717 throw new EJBException(e);
2718 } catch (IOException e) {
2719 throw new EJBException(e);
2723 private void sendMetaDataOnly(String solrUrl, FileHeader file) throws SolrServerException, IOException {
2724 CommonsHttpSolrServer solr = new CommonsHttpSolrServer(solrUrl);
2725 SolrInputDocument solrDoc = new SolrInputDocument();
2726 solrDoc.addField("id", file.getId().toString());
2727 solrDoc.addField("name", file.getName());
2728 for (FileTag t : file.getFileTags()) {
2729 solrDoc.addField("tag", t.getTag());
2735 private String tokenizeFilename(String filename){
2736 StringBuffer result = new StringBuffer();
2737 StringTokenizer tokenizer = new StringTokenizer(filename,"._");
2738 while(tokenizer.hasMoreTokens()){
2739 result.append(tokenizer.nextToken());
2742 result.append(filename);
2743 return result.toString();