2 * Copyright 2007, 2008, 2009 Electronic Business Systems Ltd.
4 * This file is part of GSS.
6 * GSS is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GSS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GSS. If not, see <http://www.gnu.org/licenses/>.
19 package gr.ebs.gss.server.ejb;
21 import static gr.ebs.gss.server.configuration.GSSConfigurationFactory.getConfiguration;
22 import gr.ebs.gss.client.exceptions.DuplicateNameException;
23 import gr.ebs.gss.client.exceptions.GSSIOException;
24 import gr.ebs.gss.client.exceptions.InsufficientPermissionsException;
25 import gr.ebs.gss.client.exceptions.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.util.ArrayList;
57 import java.util.Date;
58 import java.util.Iterator;
59 import java.util.LinkedHashSet;
60 import java.util.LinkedList;
61 import java.util.List;
62 import java.util.Locale;
63 import java.util.Random;
65 import java.util.StringTokenizer;
68 import javax.ejb.EJBException;
69 import javax.ejb.EJBTransactionRolledbackException;
70 import javax.ejb.Stateless;
71 import javax.ejb.TransactionAttribute;
72 import javax.ejb.TransactionAttributeType;
73 import javax.jms.Connection;
74 import javax.jms.ConnectionFactory;
75 import javax.jms.JMSException;
76 import javax.jms.MapMessage;
77 import javax.jms.MessageProducer;
78 import javax.jms.Queue;
79 import javax.jms.QueueConnectionFactory;
80 import javax.jms.Session;
81 import javax.naming.Context;
82 import javax.naming.InitialContext;
83 import javax.naming.NamingException;
84 import javax.persistence.PersistenceException;
85 import javax.xml.parsers.DocumentBuilder;
86 import javax.xml.parsers.DocumentBuilderFactory;
87 import javax.xml.parsers.ParserConfigurationException;
88 import javax.xml.transform.OutputKeys;
89 import javax.xml.transform.Transformer;
90 import javax.xml.transform.TransformerConfigurationException;
91 import javax.xml.transform.TransformerException;
92 import javax.xml.transform.TransformerFactory;
93 import javax.xml.transform.dom.DOMSource;
94 import javax.xml.transform.stream.StreamResult;
96 import org.apache.commons.httpclient.HttpClient;
97 import org.apache.commons.httpclient.HttpException;
98 import org.apache.commons.httpclient.NameValuePair;
99 import org.apache.commons.httpclient.methods.GetMethod;
100 import org.apache.commons.httpclient.methods.PostMethod;
101 import org.apache.commons.httpclient.methods.StringRequestEntity;
102 import org.apache.commons.lang.StringUtils;
103 import org.apache.commons.logging.Log;
104 import org.apache.commons.logging.LogFactory;
105 import org.hibernate.exception.ConstraintViolationException;
106 import org.w3c.dom.DOMException;
107 import org.w3c.dom.Document;
108 import org.w3c.dom.Node;
109 import org.w3c.dom.NodeList;
110 import org.xml.sax.SAXException;
112 import com.novell.ldap.LDAPAttribute;
113 import com.novell.ldap.LDAPAttributeSet;
114 import com.novell.ldap.LDAPConnection;
115 import com.novell.ldap.LDAPEntry;
116 import com.novell.ldap.LDAPException;
119 * The concrete implementation of the ExternalAPI interface.
124 public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
126 * The default MIME type for files without an explicit one.
128 private static final String DEFAULT_MIME_TYPE = "application/octet-stream";
131 * The size of the buffer that is used to temporarily store chunks of
132 * uploaded files, while storing them to the file repository.
134 private static final int UPLOAD_BUFFER_SIZE = 1024 * 4;
139 private static Log logger = LogFactory.getLog(ExternalAPIBean.class);
142 * Injected reference to the GSSDAO data access facade.
149 * A cached random number generator for creating unique filenames.
151 private static Random random = new Random();
154 * Mark the folder and all of its parent folders as modified from the specified user.
156 private void touchParentFolders(Folder folder, User user, Date date) {
159 AuditInfo ai = f.getAuditInfo();
160 ai.setModifiedBy(user);
161 ai.setModificationDate(date);
168 public FolderDTO getRootFolder(Long userId) throws ObjectNotFoundException {
170 throw new ObjectNotFoundException("No user specified");
171 Folder folder = dao.getRootFolder(userId);
172 return folder.getDTO();
176 public FolderDTO getFolder(final Long userId, final Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
178 throw new ObjectNotFoundException("No user specified");
179 if (folderId == null)
180 throw new ObjectNotFoundException("No folder specified");
181 final User user = dao.getEntityById(User.class, userId);
182 final Folder folder = dao.getEntityById(Folder.class, folderId);
184 if (!folder.hasReadPermission(user))
185 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
186 return folder.getDTO();
190 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUser(java.lang.Long)
192 public User getUser(Long userId) throws ObjectNotFoundException {
194 throw new ObjectNotFoundException("No user specified");
195 return dao.getEntityById(User.class, userId);
199 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUserDTO(java.lang.Long)
201 public UserDTO getUserDTO(final Long userId) throws ObjectNotFoundException {
202 return getUser(userId).getDTO();
208 * @see gr.ebs.gss.server.ejb.ExternalAPI#getGroup(java.lang.Long)
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");
234 * @see gr.ebs.gss.server.ejb.ExternalAPI#getGroups(java.lang.Long)
236 public List<GroupDTO> getGroups(final Long userId) throws ObjectNotFoundException {
238 throw new ObjectNotFoundException("No user specified");
239 final List<Group> groups = dao.getGroups(userId);
240 final List<GroupDTO> result = new ArrayList<GroupDTO>();
241 for (final Group g : groups)
242 result.add(g.getDTO());
247 public List<FileHeaderDTO> getFiles(Long userId, Long folderId, boolean ignoreDeleted)
248 throws ObjectNotFoundException, InsufficientPermissionsException {
251 throw new ObjectNotFoundException("No user specified");
252 if (folderId == null)
253 throw new ObjectNotFoundException("No folder specified");
254 User user = dao.getEntityById(User.class, userId);
255 Folder folder = dao.getEntityById(Folder.class, folderId);
256 if (!folder.hasReadPermission(user))
257 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
258 // Do the actual work.
259 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
260 List<FileHeader> files = dao.getFiles(folderId, userId, ignoreDeleted);
261 for (FileHeader f : files)
262 result.add(f.getDTO());
269 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsers(java.lang.Long,
272 public List<UserDTO> getUsers(final Long userId, final Long groupId) throws ObjectNotFoundException {
275 throw new ObjectNotFoundException("No user specified");
277 throw new ObjectNotFoundException("No group specified");
279 // Do the actual work.
280 final List<User> users = dao.getUsers(groupId);
281 final List<UserDTO> result = new ArrayList<UserDTO>();
282 for (final User u : users)
283 result.add(u.getDTO());
288 public FolderDTO createFolder(Long userId, Long parentId, String name)
289 throws DuplicateNameException, ObjectNotFoundException, InsufficientPermissionsException {
292 throw new ObjectNotFoundException("No user specified");
293 if (StringUtils.isEmpty(name))
294 throw new ObjectNotFoundException("New folder name is empty");
295 if (parentId == null)
296 throw new ObjectNotFoundException("No parent specified");
297 if (dao.existsFolderOrFile(parentId, name))
298 throw new DuplicateNameException("A folder or file with the name '" +
299 name + "' already exists at this level");
301 User creator = dao.getEntityById(User.class, userId);
303 Folder parent = null;
305 parent = dao.getEntityById(Folder.class, parentId);
306 } catch (ObjectNotFoundException onfe) {
307 // Supply a more accurate problem description.
308 throw new ObjectNotFoundException("Parent folder not found");
310 if (!parent.hasWritePermission(creator))
311 throw new InsufficientPermissionsException("You don't have the permissions" +
312 " to write to this folder");
314 // Do the actual work.
315 return createFolder(name, parent, creator);
319 * Create a new folder with the provided name, parent and owner.
324 * @return the new folder
326 private FolderDTO createFolder(String name, Folder parent, User creator) {
327 Folder folder = new Folder();
328 folder.setName(name);
329 if (parent != null) {
330 parent.addSubfolder(folder);
331 folder.setOwner(parent.getOwner());
333 folder.setOwner(creator);
335 Date now = new Date();
336 AuditInfo auditInfo = new AuditInfo();
337 auditInfo.setCreatedBy(creator);
338 auditInfo.setCreationDate(now);
339 auditInfo.setModifiedBy(creator);
340 auditInfo.setModificationDate(now);
341 folder.setAuditInfo(auditInfo);
342 touchParentFolders(folder, auditInfo.getModifiedBy(), auditInfo.getModificationDate());
345 for (Permission p : parent.getPermissions()) {
346 Permission permission = new Permission();
347 permission.setGroup(p.getGroup());
348 permission.setUser(p.getUser());
349 permission.setRead(p.getRead());
350 permission.setWrite(p.getWrite());
351 permission.setModifyACL(p.getModifyACL());
352 folder.addPermission(permission);
355 Permission permission = new Permission();
356 permission.setUser(creator);
357 permission.setRead(true);
358 permission.setWrite(true);
359 permission.setModifyACL(true);
360 folder.addPermission(permission);
363 return folder.getDTO();
367 * Deletes the given folder and all its subfolders and files
368 * Only the permissions for top folder are checked
370 * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteFolder(java.lang.Long,
373 public void deleteFolder(final Long userId, final Long folderId) throws InsufficientPermissionsException, ObjectNotFoundException {
376 throw new ObjectNotFoundException("No user specified");
377 if (folderId == null)
378 throw new ObjectNotFoundException("No folder specified");
380 // Do the actual work.
381 final Folder folder = dao.getEntityById(Folder.class, folderId);
382 final Folder parent = folder.getParent();
384 throw new ObjectNotFoundException("Deleting the root folder is not allowed");
385 final User user = dao.getEntityById(User.class, userId);
386 if (!folder.hasDeletePermission(user)) {
387 logger.info("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
388 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
390 removeSubfolderFiles(folder);
391 parent.removeSubfolder(folder);
393 touchParentFolders(parent, user, new Date());
397 * Traverses the folder and deletes all actual files (file system)
398 * regardless of permissions
402 private void removeSubfolderFiles(Folder folder) {
403 //remove files for all subfolders
404 for (Folder subfolder:folder.getSubfolders())
405 removeSubfolderFiles(subfolder);
406 //remove this folder's file bodies (actual files)
407 for (FileHeader file:folder.getFiles()) {
408 for (FileBody body:file.getBodies())
409 deleteActualFile(body.getStoredFilePath());
410 indexFile(file.getId(), true);
414 @SuppressWarnings("unchecked")
415 public List<FolderDTO> getSubfolders(Long userId, Long folderId)
416 throws ObjectNotFoundException, InsufficientPermissionsException {
418 throw new ObjectNotFoundException("No user specified");
419 if (folderId == null)
420 throw new ObjectNotFoundException("No folder specified");
421 User user = dao.getEntityById(User.class, userId);
422 Folder folder = dao.getEntityById(Folder.class, folderId);
423 if (!folder.hasReadPermission(user))
424 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
425 List<FolderDTO> result = new ArrayList<FolderDTO>();
426 if (folder.hasReadPermission(user))
427 for (Folder f : folder.getSubfolders())
428 if (f.hasReadPermission(user) && !f.isDeleted())
429 result.add(f.getDTO());
434 public FolderDTO updateFolder(Long userId, Long folderId, String folderName,
435 Set<PermissionDTO> permissions)
436 throws InsufficientPermissionsException, ObjectNotFoundException,
437 DuplicateNameException {
441 throw new ObjectNotFoundException("No user specified");
442 if (folderId == null)
443 throw new ObjectNotFoundException("No folder specified");
445 Folder folder = dao.getEntityById(Folder.class, folderId);
446 User user = dao.getEntityById(User.class, userId);
447 if (folderName != null && !folder.hasWritePermission(user))
448 throw new InsufficientPermissionsException("You don't have the necessary permissions");
449 if(permissions != null && !permissions.isEmpty() && !folder.hasModifyACLPermission(user))
450 throw new InsufficientPermissionsException("You don't have the necessary permissions");
452 Folder parent = folder.getParent();
453 if (folderName != null) {
455 if (!folder.getName().equals(folderName) && dao.existsFolderOrFile(parent.getId(), folderName))
456 throw new DuplicateNameException("A folder or file with the name '" + folderName + "' already exists at this level");
458 // Do the actual modification.
459 folder.setName(folderName);
461 if (permissions != null)
462 setFolderPermissions(user, folder, permissions);
464 folder.getAuditInfo().setModificationDate(new Date());
465 folder.getAuditInfo().setModifiedBy(user);
467 touchParentFolders(folder, user, new Date());
468 return folder.getDTO();
474 * @see gr.ebs.gss.server.ejb.ExternalAPI#createGroup(java.lang.Long,
477 public void createGroup(final Long userId, final String name) throws ObjectNotFoundException, DuplicateNameException {
480 throw new ObjectNotFoundException("No user specified");
481 if (StringUtils.isEmpty(name))
482 throw new ObjectNotFoundException("New group name is empty");
483 if (name.indexOf('/')>=0)
484 throw new IllegalArgumentException("Character '/' is not allowed in group name");
485 if (dao.existsGroup(userId, name))
486 throw new DuplicateNameException("A group with the name '" + name + "' already exists");
488 // TODO: Check permissions
490 final User owner = dao.getEntityById(User.class, userId);
492 // Do the actual work.
493 owner.createGroup(name);
499 * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteGroup(java.lang.Long,
502 public void deleteGroup(final Long userId, final Long groupId) throws ObjectNotFoundException, InsufficientPermissionsException {
505 throw new ObjectNotFoundException("No user specified");
507 throw new ObjectNotFoundException("No group specified");
509 // Do the actual work.
510 final User owner = dao.getEntityById(User.class, userId);
511 final Group group = dao.getEntityById(Group.class, groupId);
512 // Only delete the group if actually owned by the user.
513 if (group.getOwner().equals(owner)) {
514 List<Folder> folders = dao.getFoldersPermittedForGroup(userId, groupId);
515 for (Folder f : folders){
516 f.getPermissions().removeAll(group.getPermissions());
517 for(FileHeader file : f.getFiles())
518 file.getPermissions().removeAll(group.getPermissions());
520 List<FileHeader> files = dao.getSharedFilesNotInSharedFolders(userId);
521 for(FileHeader h : files)
522 h.getPermissions().removeAll(group.getPermissions());
523 owner.removeSpecifiedGroup(group);
526 else throw new InsufficientPermissionsException("You are not the owner of this group");
530 public FileHeaderDTO createFile(Long userId, Long folderId, String name, String mimeType, InputStream stream)
531 throws DuplicateNameException, ObjectNotFoundException, GSSIOException,
532 InsufficientPermissionsException, QuotaExceededException {
535 file = uploadFile(stream, userId);
536 } catch ( IOException ioe) {
537 // Supply a more accurate problem description.
538 throw new GSSIOException("Problem creating file",ioe);
540 return createFile(userId, folderId, name, mimeType, file.length(), file.getAbsolutePath());
544 * @see gr.ebs.gss.server.ejb.ExternalAPIRemote#indexFile(java.lang.Long, boolean)
546 public void indexFile(Long fileId, boolean delete) {
547 Connection qConn = null;
548 Session session = null;
549 MessageProducer sender = null;
551 Context jndiCtx = new InitialContext();
552 ConnectionFactory factory = (QueueConnectionFactory) jndiCtx.lookup("java:/JmsXA");
553 Queue queue = (Queue) jndiCtx.lookup("queue/gss-indexingQueue");
554 qConn = factory.createConnection();
555 session = qConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
556 sender = session.createProducer(queue);
558 MapMessage map = session.createMapMessage();
559 map.setObject("id", fileId);
560 map.setBoolean("delete", delete);
563 catch (NamingException e) {
564 logger.error("Index was not updated: ", e);
566 catch (JMSException e) {
567 logger.error("Index was not updated: ", e);
578 catch (JMSException e) {
587 * A helper method that generates a unique file path for a stored file. The
588 * files are stored using random hash names that are distributed evenly in
589 * a 2-level tree of subdirectories named after the first two hex characters
590 * in the name. For example, file ab1234cd5769f will be stored in the path
591 * /file-repository-root/a/b/ab1234cd5769f. The directories will be created
592 * if they don't already exist.
594 * @return a unique new file path
596 private String generateRepositoryFilePath() {
597 String filename = Long.toHexString(random.nextLong());
598 String fileRepositoryPath = getConfiguration().getString("fileRepositoryPath","/tmp");
599 File root = new File(fileRepositoryPath);
602 File firstFolder = new File(root + File.separator + filename.substring(0, 1));
603 if (!firstFolder.exists())
605 File secondFolder = new File(firstFolder + File.separator + filename.substring(1, 2));
606 if (!secondFolder.exists())
607 secondFolder.mkdir();
608 return secondFolder + File.separator + filename;
614 * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteFile(java.lang.Long,
617 public void deleteFile(final Long userId, final Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
620 throw new ObjectNotFoundException("No user specified");
622 throw new ObjectNotFoundException("No file specified");
624 // Do the actual work.
625 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
626 final Folder parent = file.getFolder();
628 throw new ObjectNotFoundException("The specified file has no parent folder");
629 final User user = dao.getEntityById(User.class, userId);
630 if (!file.hasDeletePermission(user))
631 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
632 for (final FileBody body : file.getBodies())
633 deleteActualFile(body.getStoredFilePath());
635 touchParentFolders(parent, user, new Date());
636 indexFile(fileId, true);
639 private void deleteActualFile(String filePath) {
640 if (filePath == null)
642 File file = new File(filePath);
644 logger.error("Could not delete file " + filePath);
647 public void createTag(final Long userId, final Long fileHeaderId, final String tag) throws ObjectNotFoundException {
649 throw new ObjectNotFoundException("No user specified");
650 if (fileHeaderId == null)
651 throw new ObjectNotFoundException("No file specified");
652 if (StringUtils.isEmpty(tag))
653 throw new ObjectNotFoundException("Tag is empty");
655 final User user = dao.getEntityById(User.class, userId);
656 final FileHeader fh = dao.getEntityById(FileHeader.class, fileHeaderId);
657 final Folder parent = fh.getFolder();
659 throw new ObjectNotFoundException("The specified file has no parent folder");
660 user.addTag(fh, tag);
661 touchParentFolders(parent, user, new Date());
664 public Set<String> getUserTags(final Long userId) throws ObjectNotFoundException {
665 return dao.getUserTags(userId);
668 public void updateFile(Long userId, Long fileId, String name,
669 String tagSet, Date modificationDate, Boolean versioned,
670 Boolean readForAll, Set<PermissionDTO> permissions)
671 throws DuplicateNameException, ObjectNotFoundException, InsufficientPermissionsException {
673 throw new ObjectNotFoundException("No user specified");
675 throw new ObjectNotFoundException("No file specified");
676 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
677 final Folder parent = file.getFolder();
679 throw new ObjectNotFoundException("The specified file has no parent folder");
681 User user = dao.getEntityById(User.class, userId);
682 // Check permissions for modifying the file metadata.
683 if ((name != null || tagSet != null || modificationDate != null || versioned != null) && !file.hasWritePermission(user))
684 throw new InsufficientPermissionsException("User " + user.getId() + " cannot update file " + file.getName() + "(" + file.getId() + ")");
685 // Check permissions for making file public.
686 if (readForAll != null && !user.equals(file.getOwner()))
687 throw new InsufficientPermissionsException("Only the owner can make a file public or not public");
688 // Check permissions for modifying the ACL.
689 if(permissions != null && !permissions.isEmpty() && !file.hasModifyACLPermission(user))
690 throw new InsufficientPermissionsException("User " + user.getId() + " cannot update the permissions on file " + file.getName() + "(" + file.getId() + ")");
693 // Do plain check for file already exists.
694 // Extreme concurrency case should be caught by constraint violation later.
695 if (dao.existsFolderOrFile(parent.getId(), name)) throw new DuplicateNameException("A file or folder with the name '" + name + "' already exists");
699 if (modificationDate != null)
700 file.getAuditInfo().setModificationDate(modificationDate);
702 file.getAuditInfo().setModificationDate(new Date());
703 file.getAuditInfo().setModifiedBy(user);
705 List<FileTag> tags = file.getFileTags();
706 if (tagSet != null) {
707 Iterator<FileTag> i = tags.iterator();
708 while (i.hasNext()) {
709 FileTag tag = i.next();
716 StringTokenizer st = new StringTokenizer(tagSet, ",");
717 while (st.hasMoreTokens())
718 new FileTag(user, file, st.nextToken().trim());
720 if (versioned != null && !file.isVersioned() == versioned) {
721 if (file.isVersioned())
722 removeOldVersions(userId, fileId);
723 file.setVersioned(versioned);
725 if (readForAll != null && user.equals(file.getOwner()))
726 file.setReadForAll(readForAll);
727 if (permissions != null && !permissions.isEmpty())
728 setFilePermissions(file, permissions);
731 * Force constraint violation to manifest itself here.
732 * This should cover extreme concurrency cases that the simple check
733 * above hasn't caught.
738 catch (EJBTransactionRolledbackException e) {
739 Throwable cause = e.getCause();
740 if (cause instanceof PersistenceException && cause.getCause() instanceof ConstraintViolationException)
741 throw new DuplicateNameException("A file or folder with the name '" + name + "' already exists");
745 touchParentFolders(parent, user, new Date());
747 // Re-index the file if it was modified.
748 if (name != null || tagSet != null)
749 indexFile(fileId, false);
753 public InputStream getFileContents(Long userId, Long fileId)
754 throws ObjectNotFoundException, InsufficientPermissionsException {
756 throw new ObjectNotFoundException("No user specified");
758 throw new ObjectNotFoundException("No file specified");
760 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
761 User user = dao.getEntityById(User.class, userId);
762 if (!header.hasReadPermission(user)) {
763 logger.info("User " + user.getId() + " cannot read file " + header.getName() + "(" + fileId + ")");
764 throw new InsufficientPermissionsException("You don't have the necessary permissions");
767 File f = new File(header.getCurrentBody().getStoredFilePath());
769 return new FileInputStream(f);
770 } catch (FileNotFoundException e) {
771 logger.error("Could not locate the contents of file " + f.getAbsolutePath());
772 throw new ObjectNotFoundException("The file contents could not be located");
777 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFileContents(java.lang.Long, java.lang.Long, java.lang.Long)
779 public InputStream getFileContents(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
781 throw new ObjectNotFoundException("No user specified");
783 throw new ObjectNotFoundException("No file specified");
785 throw new ObjectNotFoundException("No file specified");
787 final FileHeader header = dao.getEntityById(FileHeader.class, fileId);
788 final FileBody body = dao.getEntityById(FileBody.class, bodyId);
789 final User user = dao.getEntityById(User.class, userId);
790 if (!header.hasReadPermission(user)) {
791 logger.info("User " + user.getId() + " cannot read file " + header.getName() + "(" + fileId + ")");
792 throw new InsufficientPermissionsException("You don't have the necessary permissions");
795 File f = new File(body.getStoredFilePath());
797 return new FileInputStream(f);
798 } catch (FileNotFoundException e) {
799 logger.error("Could not locate the contents of file " + f.getAbsolutePath());
800 throw new ObjectNotFoundException("The file contents could not be located");
805 public FileHeaderDTO getFile(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
807 throw new ObjectNotFoundException("No user specified");
809 throw new ObjectNotFoundException("No file specified");
810 final User user = dao.getEntityById(User.class, userId);
811 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
812 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
813 throw new InsufficientPermissionsException("You don't have the necessary permissions");
814 return file.getDTO();
818 public FileBodyDTO getFileBody(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
820 throw new ObjectNotFoundException("No user specified");
822 throw new ObjectNotFoundException("No file specified");
823 User user = dao.getEntityById(User.class, userId);
824 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
825 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
826 throw new InsufficientPermissionsException("You don't have the necessary permissions");
827 FileBody body = dao.getEntityById(FileBody.class, bodyId);
828 return body.getDTO();
832 public Object getResourceAtPath(Long ownerId, String path, boolean ignoreDeleted)
833 throws ObjectNotFoundException {
835 throw new ObjectNotFoundException("No user specified");
836 if (StringUtils.isEmpty(path))
837 throw new ObjectNotFoundException("No path specified");
839 User owner = dao.getEntityById(User.class, ownerId);
840 List<String> pathElements = new ArrayList<String>();
841 StringTokenizer st = new StringTokenizer(path, "/");
842 while (st.hasMoreTokens())
843 pathElements.add(st.nextToken());
844 if (pathElements.size() < 1)
845 return getRootFolder(owner.getId());
846 // Store the last element, since it requires special handling.
847 String lastElement = pathElements.remove(pathElements.size() - 1);
848 FolderDTO cursor = getRootFolder(owner.getId());
849 // Traverse and verify the specified folder path.
850 for (String pathElement : pathElements) {
851 cursor = getFolder(cursor.getId(), pathElement);
852 if (cursor.isDeleted())
853 throw new ObjectNotFoundException("Folder " + cursor.getPath() + " not found");
856 // Use the lastElement to retrieve the actual resource.
857 Object resource = null;
859 FileHeaderDTO file = getFile(cursor.getId(), lastElement);
860 if (ignoreDeleted && file.isDeleted())
861 throw new ObjectNotFoundException("Resource not found");
863 } catch (ObjectNotFoundException e) {
864 // Perhaps the requested resource is not a file, so
865 // check for folders as well.
866 FolderDTO folder = getFolder(cursor.getId(), lastElement);
867 if (ignoreDeleted && folder.isDeleted())
868 throw new ObjectNotFoundException("Resource not found");
875 * Retrieve a file for the specified user that has the specified name and
876 * its parent folder has id equal to folderId.
878 * @param userId the ID of the current user
879 * @param folderId the ID of the parent folder
880 * @param name the name of the requested file
881 * @return the file found
882 * @throws ObjectNotFoundException if the specified folder or file was not
883 * found, with the exception message mentioning the precise
886 private FileHeaderDTO getFile(Long folderId, String name) throws ObjectNotFoundException {
887 if (folderId == null)
888 throw new ObjectNotFoundException("No parent folder specified");
889 if (StringUtils.isEmpty(name))
890 throw new ObjectNotFoundException("No file specified");
892 FileHeader file = dao.getFile(folderId, name);
893 return file.getDTO();
897 * Retrieve a folder for the specified user that has the specified name and
898 * its parent folder has id equal to parentId.
900 * @param parentId the ID of the parent folder
901 * @param name the name of the requested folder
902 * @return the folder found
903 * @throws ObjectNotFoundException if the specified folder or parent was not
904 * found, with the exception message mentioning the precise
907 private FolderDTO getFolder(Long parentId, String name) throws ObjectNotFoundException {
908 if (parentId == null)
909 throw new ObjectNotFoundException("No parent folder specified");
910 if (StringUtils.isEmpty(name))
911 throw new ObjectNotFoundException("No folder specified");
913 Folder folder = dao.getFolder(parentId, name);
914 return folder.getDTO();
917 private FileHeaderDTO updateFileContents(Long userId, Long fileId, String mimeType, InputStream resourceInputStream) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
920 file = uploadFile(resourceInputStream, userId);
921 } catch ( IOException ioe) {
922 // Supply a more accurate problem description.
923 throw new GSSIOException("Problem creating file",ioe);
925 return updateFileContents(userId, fileId, mimeType, file.length(), file.getAbsolutePath());
929 public void copyFile(Long userId, Long fileId, String dest) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
931 throw new ObjectNotFoundException("No user specified");
933 throw new ObjectNotFoundException("No file specified");
934 if (StringUtils.isEmpty(dest))
935 throw new ObjectNotFoundException("No destination specified");
937 Object destination = getResourceAtPath(userId, getParentPath(dest), true);
938 if (!(destination instanceof FolderDTO))
939 throw new ObjectNotFoundException("Destination parent folder not found");
940 FolderDTO parent = (FolderDTO) destination;
941 copyFile(userId, fileId, parent.getId(), getLastElement(dest));
945 public void copyFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
947 throw new ObjectNotFoundException("No user specified");
949 throw new ObjectNotFoundException("No owner specified");
951 throw new ObjectNotFoundException("No file specified");
952 if (StringUtils.isEmpty(dest))
953 throw new ObjectNotFoundException("No destination specified");
955 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
956 if (!(destination instanceof FolderDTO))
957 throw new ObjectNotFoundException("Destination parent folder not found");
958 FolderDTO parent = (FolderDTO) destination;
959 copyFile(userId, fileId, parent.getId(), getLastElement(dest));
963 public void copyFile(Long userId, Long fileId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
965 throw new ObjectNotFoundException("No user specified");
967 throw new ObjectNotFoundException("No file specified");
969 throw new ObjectNotFoundException("No destination specified");
970 if (StringUtils.isEmpty(destName))
971 throw new ObjectNotFoundException("No destination file name specified");
973 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
974 Folder destination = dao.getEntityById(Folder.class, destId);
975 User user = dao.getEntityById(User.class, userId);
976 if (!file.hasReadPermission(user) || !destination.hasWritePermission(user))
977 throw new InsufficientPermissionsException("You don't have the necessary permissions");
978 boolean versioned = file.isVersioned();
979 int versionsNumber = file.getBodies().size();
980 FileBody oldestBody = file.getBodies().get(0);
981 assert oldestBody != null;
982 File contents = new File(oldestBody.getStoredFilePath());
984 createFile(user.getId(), destination.getId(), destName, oldestBody.getMimeType(), new FileInputStream(contents));
985 FileHeader copiedFile = dao.getFile(destination.getId(), destName);
986 copiedFile.setVersioned(versioned);
988 if (versionsNumber > 1)
989 for (int i = 1; i < versionsNumber; i++) {
990 FileBody body = file.getBodies().get(i);
992 contents = new File(body.getStoredFilePath());
993 updateFileContents(user.getId(), copiedFile.getId(), body.getMimeType(), new FileInputStream(contents));
995 List<FileTag> tags = file.getFileTags();
996 for (FileTag tag : tags)
997 createTag(userId, copiedFile.getId(), tag.getTag());
999 } catch (FileNotFoundException e) {
1000 throw new ObjectNotFoundException("File contents not found for file " + contents.getAbsolutePath());
1006 public void copyFolder(Long userId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
1008 throw new ObjectNotFoundException("No user specified");
1009 if (folderId == null)
1010 throw new ObjectNotFoundException("No folder specified");
1011 if (StringUtils.isEmpty(dest))
1012 throw new ObjectNotFoundException("No destination specified");
1014 Object destination = getResourceAtPath(userId, getParentPath(dest), true);
1015 if (!(destination instanceof FolderDTO))
1016 throw new ObjectNotFoundException("Destination folder not found");
1017 FolderDTO parent = (FolderDTO) destination;
1018 copyFolder(userId, folderId, parent.getId(), getLastElement(dest));
1022 public void copyFolder(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
1024 throw new ObjectNotFoundException("No user specified");
1025 if (folderId == null)
1026 throw new ObjectNotFoundException("No folder specified");
1028 throw new ObjectNotFoundException("No destination specified");
1029 if (StringUtils.isEmpty(destName))
1030 throw new ObjectNotFoundException("No destination folder name specified");
1031 Folder folder = dao.getEntityById(Folder.class, folderId);
1032 Folder destination = dao.getEntityById(Folder.class, destId);
1033 User user = dao.getEntityById(User.class, userId);
1034 if (!destination.hasWritePermission(user) || !folder.hasReadPermission(user))
1035 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1036 createFolder(user.getId(), destination.getId(), destName);
1040 public void copyFolderStructureToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1042 throw new ObjectNotFoundException("No user specified");
1043 if (ownerId == null)
1044 throw new ObjectNotFoundException("No owner specified");
1045 if (folderId == null)
1046 throw new ObjectNotFoundException("No folder specified");
1047 if (StringUtils.isEmpty(dest))
1048 throw new ObjectNotFoundException("No destination specified");
1050 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1051 if (!(destination instanceof FolderDTO))
1052 throw new ObjectNotFoundException("Destination folder not found");
1053 FolderDTO parent = (FolderDTO) destination;
1054 copyFolderStructure(userId, folderId, parent.getId(), getLastElement(dest));
1058 public void copyFolderStructure(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1060 throw new ObjectNotFoundException("No user specified");
1061 if (folderId == null)
1062 throw new ObjectNotFoundException("No folder specified");
1064 throw new ObjectNotFoundException("No destination specified");
1065 if (StringUtils.isEmpty(destName))
1066 throw new ObjectNotFoundException("No destination folder name specified");
1068 Folder folder = dao.getEntityById(Folder.class, folderId);
1069 Folder destination = dao.getEntityById(Folder.class, destId);
1070 final User user = dao.getEntityById(User.class, userId);
1071 // XXX: quick fix need to copy only visible items to user (Source
1073 if (!folder.getOwner().getId().equals(userId) && !folder.hasReadPermission(user))
1075 if(folder.isDeleted())//do not copy trashed folder and contents
1077 if (!destination.hasWritePermission(user) || !folder.hasReadPermission(user))
1078 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1079 createFolder(user.getId(), destination.getId(), destName);
1080 Folder createdFolder = dao.getFolder(destination.getId(), destName);
1081 List<FileHeader> files = folder.getFiles();
1083 for (FileHeader file : files)
1084 if(!file.isDeleted())
1085 copyFile(userId, file.getId(), createdFolder.getId(), file.getName());
1086 List<Folder> subFolders = folder.getSubfolders();
1087 if (subFolders != null)
1088 for (Folder sub : subFolders)
1089 if(!sub.getId().equals(createdFolder.getId()))
1090 copyFolderStructure(userId, sub.getId(), createdFolder.getId(), sub.getName());
1095 * For a provided path, remove the last element and return the rest, that is
1096 * the path of the parent folder.
1098 * @param path the specified path
1099 * @return the path of the parent folder
1100 * @throws ObjectNotFoundException if the provided string contains no path
1103 private String getParentPath(String path) throws ObjectNotFoundException {
1104 int lastDelimiter = path.lastIndexOf('/');
1105 if (lastDelimiter == 0)
1107 if (lastDelimiter == -1)
1109 throw new ObjectNotFoundException("There is no parent in the path: " + path);
1110 else if (lastDelimiter < path.length() - 1)
1111 // Return the part before the delimiter.
1112 return path.substring(0, lastDelimiter);
1114 // Remove the trailing delimiter and then recurse.
1115 String strippedTrail = path.substring(0, lastDelimiter);
1116 return getParentPath(strippedTrail);
1121 * Get the last element in a path that denotes the file or folder name.
1123 * @param path the provided path
1124 * @return the last element in the path
1126 private String getLastElement(String path) {
1127 int lastDelimiter = path.lastIndexOf('/');
1128 if (lastDelimiter == -1)
1131 else if (lastDelimiter < path.length() - 1)
1132 // Return the part after the delimiter.
1133 return path.substring(lastDelimiter + 1);
1135 // Remove the trailing delimiter and then recurse.
1136 String strippedTrail = path.substring(0, lastDelimiter);
1137 return getLastElement(strippedTrail);
1142 public void moveFileToTrash(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1144 throw new ObjectNotFoundException("No user specified");
1146 throw new ObjectNotFoundException("No file specified");
1148 // Do the actual work.
1149 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1150 Folder parent = file.getFolder();
1152 throw new ObjectNotFoundException("The specified file has no parent folder");
1153 User user = dao.getEntityById(User.class, userId);
1154 if (!file.hasDeletePermission(user))
1155 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
1157 file.setDeleted(true);
1159 touchParentFolders(parent, user, new Date());
1163 public void moveFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, InsufficientPermissionsException, QuotaExceededException {
1165 throw new ObjectNotFoundException("No user specified");
1166 if (ownerId == null)
1167 throw new ObjectNotFoundException("No owner specified");
1169 throw new ObjectNotFoundException("No file specified");
1170 if (StringUtils.isEmpty(dest))
1171 throw new ObjectNotFoundException("No destination specified");
1173 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1174 if (!(destination instanceof FolderDTO))
1175 throw new ObjectNotFoundException("Destination parent folder not found");
1176 FolderDTO parent = (FolderDTO) destination;
1177 moveFile(userId, fileId, parent.getId(), getLastElement(dest));
1181 public void moveFile(Long userId, Long fileId, Long destId, String destName) throws InsufficientPermissionsException, ObjectNotFoundException, QuotaExceededException {
1183 throw new ObjectNotFoundException("No user specified");
1185 throw new ObjectNotFoundException("No file specified");
1187 throw new ObjectNotFoundException("No destination specified");
1188 if (StringUtils.isEmpty(destName))
1189 throw new ObjectNotFoundException("No destination file name specified");
1191 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1192 Folder source = file.getFolder();
1193 Folder destination = dao.getEntityById(Folder.class, destId);
1195 User owner = dao.getEntityById(User.class, userId);
1196 if (!file.hasDeletePermission(owner) || !destination.hasWritePermission(owner))
1197 throw new InsufficientPermissionsException("User " + owner.getId() + " cannot move file " + file.getName() + "(" + file.getId() + ")");
1199 // if the destination folder belongs to another user:
1200 if (!file.getOwner().equals(destination.getOwner())) {
1201 // (a) check if the destination quota allows the move
1202 if(getQuotaLeft(destination.getOwner().getId()) < file.getTotalSize())
1203 throw new QuotaExceededException("Not enough free space available");
1204 User newOwner = destination.getOwner();
1205 // (b) if quota OK, change the owner of the file
1206 file.setOwner(newOwner);
1207 // if the file has no permission for the new owner, add it
1208 Permission ownerPermission = null;
1209 for (final Permission p : file.getPermissions())
1210 if (p.getUser() != null)
1211 if (p.getUser().equals(newOwner)) {
1212 ownerPermission = p;
1215 if (ownerPermission == null) {
1216 ownerPermission = new Permission();
1217 ownerPermission.setUser(newOwner);
1218 file.addPermission(ownerPermission);
1220 ownerPermission.setRead(true);
1221 ownerPermission.setWrite(true);
1222 ownerPermission.setModifyACL(true);
1224 // move the file to the destination folder
1225 file.setFolder(destination);
1226 touchParentFolders(source, owner, new Date());
1227 touchParentFolders(destination, owner, new Date());
1231 public void moveFolderToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, InsufficientPermissionsException, QuotaExceededException {
1233 throw new ObjectNotFoundException("No user specified");
1234 if (ownerId == null)
1235 throw new ObjectNotFoundException("No owner specified");
1236 if (folderId == null)
1237 throw new ObjectNotFoundException("No folder specified");
1238 if (StringUtils.isEmpty(dest))
1239 throw new ObjectNotFoundException("No destination specified");
1241 Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1242 if (!(destination instanceof FolderDTO))
1243 throw new ObjectNotFoundException("Destination parent folder not found");
1244 FolderDTO parent = (FolderDTO) destination;
1245 moveFolder(userId, folderId, parent.getId(), getLastElement(dest));
1249 public void moveFolder(Long userId, Long folderId, Long destId, String destName)
1250 throws ObjectNotFoundException, InsufficientPermissionsException,
1251 QuotaExceededException {
1252 Folder source = dao.getEntityById(Folder.class, folderId);
1253 Folder destination = dao.getEntityById(Folder.class, destId);
1254 User user = dao.getEntityById(User.class, userId);
1255 User sourceOwner = source.getOwner();
1256 User destinationOwner = destination.getOwner();
1257 // Do not move trashed folders and contents.
1258 if (source.isDeleted())
1260 // Check permissions.
1261 if (!destination.hasWritePermission(user)
1262 || !source.hasReadPermission(user)
1263 || !source.hasWritePermission(user))
1264 throw new InsufficientPermissionsException("You don't have the " +
1265 "necessary permissions");
1266 // Use the same timestamp for all subsequent modifications to make
1267 // changes appear simultaneous.
1268 Date now = new Date();
1269 // If source and destination are not in the same user's namespace,
1270 // change owners and check quota.
1271 if (!sourceOwner.equals(destinationOwner)) {
1272 changeOwner(source, destinationOwner, user, now);
1273 if (getQuotaLeft(destinationOwner.getId()) < 0)
1274 throw new QuotaExceededException("Not enough free space " +
1275 "available in destination folder");
1277 // Perform the move.
1278 Folder oldParent = source.getParent();
1279 oldParent.removeSubfolder(source);
1280 destination.addSubfolder(source);
1281 // Mark the former parent and destination trees upwards as modified.
1282 touchParentFolders(oldParent, user, now);
1283 touchParentFolders(source, user, now);
1287 * Recursively change the owner of the specified folder and all of its
1288 * contents to the specified owner. Also mark them all as modified with the
1289 * specified modifier and modificationDate.
1291 private void changeOwner(Folder folder, User owner, User modifier, Date modificationDate) {
1292 for (FileHeader file: folder.getFiles()) {
1293 file.setOwner(owner);
1294 file.getAuditInfo().setModificationDate(modificationDate);
1295 file.getAuditInfo().setModifiedBy(modifier);
1297 for (Folder sub: folder.getSubfolders())
1298 changeOwner(sub, owner, modifier, modificationDate);
1299 folder.setOwner(owner);
1300 folder.getAuditInfo().setModificationDate(modificationDate);
1301 folder.getAuditInfo().setModifiedBy(modifier);
1305 public List<FileHeaderDTO> getDeletedFiles(Long userId) throws ObjectNotFoundException {
1308 throw new ObjectNotFoundException("No user specified");
1310 // Do the actual work.
1311 final List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1312 final List<FileHeader> files = dao.getDeletedFiles(userId);
1313 for (final FileHeader f : files)
1314 result.add(f.getDTO());
1319 public void removeFileFromTrash(Long userId, Long fileId)
1320 throws ObjectNotFoundException, InsufficientPermissionsException {
1322 throw new ObjectNotFoundException("No user specified");
1324 throw new ObjectNotFoundException("No file specified");
1326 // Do the actual work.
1327 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1328 Folder parent = file.getFolder();
1330 throw new ObjectNotFoundException("The specified file has no parent folder");
1331 User user = dao.getEntityById(User.class, userId);
1332 if (!file.hasDeletePermission(user))
1333 throw new InsufficientPermissionsException("User " + user.getUsername() +
1334 " cannot restore file " + file.getName());
1336 file.setDeleted(false);
1338 touchParentFolders(parent, user, new Date());
1342 public void moveFolderToTrash(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
1344 throw new ObjectNotFoundException("No user specified");
1345 if (folderId == null)
1346 throw new ObjectNotFoundException("No folder specified");
1347 Folder folder = dao.getEntityById(Folder.class, folderId);
1348 User user = dao.getEntityById(User.class, userId);
1349 if (!folder.hasDeletePermission(user))
1350 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1351 folder.setDeleted(true);
1353 touchParentFolders(folder, user, new Date());
1354 for (FileHeader file : folder.getFiles())
1355 moveFileToTrash(userId, file.getId());
1356 for (Folder subFolder : folder.getSubfolders())
1357 moveFolderToTrash(userId, subFolder.getId());
1362 public void removeFolderFromTrash(Long userId, Long folderId)
1363 throws ObjectNotFoundException, InsufficientPermissionsException {
1365 throw new ObjectNotFoundException("No user specified");
1366 if (folderId == null)
1367 throw new ObjectNotFoundException("No folder specified");
1368 Folder folder = dao.getEntityById(Folder.class, folderId);
1369 User user = dao.getEntityById(User.class, userId);
1370 if (!folder.hasDeletePermission(user))
1371 throw new InsufficientPermissionsException("User " + user.getUsername() +
1372 " cannot restore folder " + folder.getName());
1373 folder.setDeleted(false);
1374 for (FileHeader file : folder.getFiles())
1375 removeFileFromTrash(userId, file.getId());
1376 for (Folder subFolder : folder.getSubfolders())
1377 removeFolderFromTrash(userId, subFolder.getId());
1379 touchParentFolders(folder, user, new Date());
1383 public List<FolderDTO> getDeletedRootFolders(Long userId) throws ObjectNotFoundException {
1384 List<Folder> folders = dao.getDeletedRootFolders(userId);
1385 List<FolderDTO> result = new ArrayList<FolderDTO>();
1386 for (Folder folder : folders)
1387 result.add(folder.getDTO());
1392 public void emptyTrash(Long userId) throws ObjectNotFoundException, InsufficientPermissionsException {
1393 List<FolderDTO> deletedRootFolders = getDeletedRootFolders(userId);
1394 for (FolderDTO fdto : deletedRootFolders)
1395 deleteFolder(userId, fdto.getId());
1396 List<FileHeaderDTO> deletedFiles = getDeletedFiles(userId);
1397 for (FileHeaderDTO filedto : deletedFiles)
1398 deleteFile(userId, filedto.getId());
1402 public void restoreTrash(Long userId) throws ObjectNotFoundException, InsufficientPermissionsException {
1403 List<FolderDTO> deletedRootFolders = getDeletedRootFolders(userId);
1404 for (FolderDTO fdto : deletedRootFolders)
1405 removeFolderFromTrash(userId, fdto.getId());
1406 List<FileHeaderDTO> deletedFiles = getDeletedFiles(userId);
1407 for (FileHeaderDTO filedto : deletedFiles)
1408 removeFileFromTrash(userId, filedto.getId());
1412 public User createUser(String username, String name, String mail,
1413 String idp, String idpid) throws ObjectNotFoundException {
1414 if (username == null)
1415 throw new ObjectNotFoundException("No username specified");
1417 throw new ObjectNotFoundException("No name specified");
1419 User user = new User();
1420 user.setUsername(username);
1422 user.setEmail(mail);
1423 user.setIdentityProvider(idp);
1424 user.setIdentityProviderId(idpid);
1425 Date now = new Date();
1426 AuditInfo auditInfo = new AuditInfo();
1427 auditInfo.setCreationDate(now);
1428 auditInfo.setModificationDate(now);
1429 user.setAuditInfo(auditInfo);
1430 user.generateAuthToken();
1431 user.generateWebDAVPassword();
1432 // Set the default user class to the one with the lowest quota.
1433 user.setUserClass(getUserClasses().get(0));
1435 // Make sure we get an ID in the user object.
1437 // Create the root folder for the user.
1438 createFolder(user.getName(), null, user);
1443 public List<UserClass> getUserClasses() {
1444 List<UserClass> classes = dao.getUserClasses();
1445 // Create a default user class for first-time use. Afterwards, the
1446 // admin should modify or add to the userclass table.
1447 if (classes.size() == 0) {
1448 UserClass defaultClass = new UserClass();
1449 defaultClass.setName("default");
1450 Long defaultQuota = getConfiguration().getLong("quota", new Long(52428800L));
1451 defaultClass.setQuota(defaultQuota);
1452 dao.create(defaultClass);
1453 classes.add(defaultClass);
1459 public User findUserByEmail(String email) {
1460 return dao.findUserByEmail(email);
1464 public void updateUser(User user) {
1469 public User findUser(String username) {
1470 if (username == null)
1472 return dao.findUser(username);
1476 public User updateUserToken(Long userId) throws ObjectNotFoundException {
1478 throw new ObjectNotFoundException("No user specified");
1479 User user = dao.getEntityById(User.class, userId);
1480 user.generateAuthToken();
1485 public Set<PermissionDTO> getFolderPermissions(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
1487 throw new ObjectNotFoundException("No user specified");
1488 if (folderId == null)
1489 throw new ObjectNotFoundException("No folder specified");
1490 User user = dao.getEntityById(User.class, userId);
1491 Folder folder = dao.getEntityById(Folder.class, folderId);
1492 if(!folder.hasReadPermission(user))
1493 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1494 Set<Permission> perms = folder.getPermissions();
1495 Set<PermissionDTO> result = new LinkedHashSet<PermissionDTO>();
1496 for (Permission perm : perms)
1497 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId()))
1498 result.add(perm.getDTO());
1499 for (Permission perm : perms)
1500 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId())) {
1502 result.add(perm.getDTO());
1508 * Set the provided permissions as the new permissions of the specified
1513 * @param permissions
1514 * @throws ObjectNotFoundException
1515 * @throws InsufficientPermissionsException
1517 private void setFolderPermissions(User user, Folder folder, Set<PermissionDTO> permissions) throws ObjectNotFoundException, InsufficientPermissionsException {
1518 if (permissions != null && !permissions.isEmpty()) {
1519 User owner = folder.getOwner();
1520 PermissionDTO ownerPerm = null;
1521 for (PermissionDTO dto : permissions)
1522 if (dto.getUser() != null && dto.getUser().getId().equals(owner.getId())) {
1526 if (ownerPerm == null || !ownerPerm.hasRead() || !ownerPerm.hasWrite() || !ownerPerm.hasModifyACL())
1527 throw new InsufficientPermissionsException("Can't remove permissions from owner");
1528 // Delete previous entries
1529 for (Permission perm: folder.getPermissions())
1531 folder.getPermissions().clear();
1532 for (PermissionDTO dto : permissions) {
1533 // Skip 'empty' permission entries.
1534 if (!dto.getRead() && !dto.getWrite() && !dto.getModifyACL()) continue;
1535 folder.addPermission(getPermission(dto));
1538 for (FileHeader file : folder.getFiles()) {
1539 setFilePermissions(file, permissions);
1540 Date now = new Date();
1541 file.getAuditInfo().setModificationDate(now);
1542 file.getAuditInfo().setModifiedBy(user);
1544 for (Folder sub : folder.getSubfolders())
1545 setFolderPermissions(user, sub, permissions);
1549 private Permission getPermission(PermissionDTO dto) throws ObjectNotFoundException {
1550 Permission res = new Permission();
1551 if (dto.getGroup() != null)
1552 res.setGroup(dao.getEntityById(Group.class, dto.getGroup().getId()));
1553 else if (dto.getUser() != null)
1554 if (dto.getUser().getId() == null)
1555 res.setUser(dao.getUser(dto.getUser().getUsername()));
1557 res.setUser(dao.getEntityById(User.class, dto.getUser().getId()));
1558 res.setRead(dto.hasRead());
1559 res.setWrite(dto.hasWrite());
1560 res.setModifyACL(dto.hasModifyACL());
1565 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsersByUserNameLike(java.lang.String)
1568 public List<UserDTO> getUsersByUserNameLike(String username) {
1569 List<User> users = dao.getUsersByUserNameLike(username);
1570 List<UserDTO> result = new ArrayList<UserDTO>();
1571 for (User u : users)
1572 result.add(u.getDTO());
1578 * @see gr.ebs.gss.server.ejb.ExternalAPI#addUserToGroup(java.lang.Long, java.lang.Long, java.lang.Long)
1581 public void addUserToGroup(Long userId, Long groupId, Long userToAddId) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
1583 throw new ObjectNotFoundException("No user specified");
1584 if (groupId == null)
1585 throw new ObjectNotFoundException("No group specified");
1586 if (userToAddId == null)
1587 throw new ObjectNotFoundException("No user to add specified");
1588 User user = dao.getEntityById(User.class, userId);
1589 Group group = dao.getEntityById(Group.class, groupId);
1590 if (!group.getOwner().equals(user))
1591 throw new InsufficientPermissionsException();
1592 User userToAdd = dao.getEntityById(User.class, userToAddId);
1593 if (group.contains(userToAdd))
1594 throw new DuplicateNameException("User already exists in group");
1595 group.getMembers().add(userToAdd);
1601 public void invalidateUserToken(Long userId) throws ObjectNotFoundException {
1603 throw new ObjectNotFoundException("No user specified");
1604 User user = dao.getEntityById(User.class, userId);
1605 user.invalidateAuthToken();
1610 public List<FolderDTO> getSharedRootFolders(Long userId) throws ObjectNotFoundException {
1612 throw new ObjectNotFoundException("No user specified");
1613 List<Folder> folders = dao.getSharedRootFolders(userId);
1614 List<FolderDTO> result = new ArrayList<FolderDTO>();
1615 for (Folder f : folders) {
1616 FolderDTO dto = f.getDTO();
1617 dto.setSubfolders(getSharedSubfolders(userId, f.getId()));
1624 * @see gr.ebs.gss.server.ejb.ExternalAPI#removeMemberFromGroup(java.lang.Long, java.lang.Long, java.lang.Long)
1627 public void removeMemberFromGroup(Long userId, Long groupId, Long memberId) throws ObjectNotFoundException, InsufficientPermissionsException {
1629 throw new ObjectNotFoundException("No user specified");
1630 if (groupId == null)
1631 throw new ObjectNotFoundException("No group specified");
1632 if (memberId == null)
1633 throw new ObjectNotFoundException("No member specified");
1634 User owner = dao.getEntityById(User.class, userId);
1635 Group group = dao.getEntityById(Group.class, groupId);
1636 User member = dao.getEntityById(User.class, memberId);
1637 if (!group.getOwner().equals(owner))
1638 throw new InsufficientPermissionsException("User is not the owner of the group");
1639 group.removeMemberFromGroup(member);
1645 public List<UserDTO> getUsersSharingFoldersForUser(Long userId) throws ObjectNotFoundException {
1646 List<User> users = dao.getUsersSharingFoldersForUser(userId);
1647 List<User> usersFiles = dao.getUsersSharingFilesForUser(userId);
1648 List<UserDTO> res = new ArrayList<UserDTO>();
1649 for (User u : users)
1650 res.add(u.getDTO());
1651 for(User fu : usersFiles)
1652 if(!users.contains(fu))
1653 res.add(fu.getDTO());
1658 public Set<PermissionDTO> getFilePermissions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1660 throw new ObjectNotFoundException("No user specified");
1662 throw new ObjectNotFoundException("No folder specified");
1663 User user = dao.getEntityById(User.class, userId);
1664 FileHeader folder = dao.getEntityById(FileHeader.class, fileId);
1665 if(!folder.hasReadPermission(user))
1666 throw new InsufficientPermissionsException("You don't have the necessary permissions");
1667 Set<Permission> perms = folder.getPermissions();
1668 Set<PermissionDTO> result = new LinkedHashSet<PermissionDTO>();
1669 for (Permission perm : perms)
1670 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId()))
1671 result.add(perm.getDTO());
1672 for (Permission perm : perms)
1673 if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId())) {
1675 result.add(perm.getDTO());
1680 * Set the provided permissions as the new permissions of the specified
1681 * file. This method sets the modification date/user attributes to the
1682 * current values as a side effect.
1685 * @param permissions
1686 * @throws ObjectNotFoundException
1687 * @throws InsufficientPermissionsException
1689 private void setFilePermissions(FileHeader file,
1690 Set<PermissionDTO> permissions)
1691 throws ObjectNotFoundException, InsufficientPermissionsException {
1692 if (permissions != null && !permissions.isEmpty()) {
1693 PermissionDTO ownerPerm = null;
1694 for (PermissionDTO dto : permissions)
1695 if (dto.getUser() != null && dto.getUser().getId().equals(file.getOwner().getId())) {
1699 if (ownerPerm == null || !ownerPerm.hasRead() || !ownerPerm.hasWrite() || !ownerPerm.hasModifyACL())
1700 throw new InsufficientPermissionsException("Can't remove permissions from owner");
1701 // Delete previous entries.
1702 for (Permission perm: file.getPermissions())
1704 file.getPermissions().clear();
1705 for (PermissionDTO dto : permissions) {
1706 // Skip 'empty' permission entries.
1707 if (!dto.getRead() && !dto.getWrite() && !dto.getModifyACL()) continue;
1708 file.addPermission(getPermission(dto));
1715 public List<FileHeaderDTO> getSharedFilesNotInSharedFolders(Long userId) throws ObjectNotFoundException {
1717 throw new ObjectNotFoundException("No user specified");
1718 List<FileHeader> files = dao.getSharedFilesNotInSharedFolders(userId);
1719 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1720 for (FileHeader f : files)
1721 result.add(f.getDTO());
1726 public List<FileHeaderDTO> getSharedFiles(Long userId) throws ObjectNotFoundException {
1728 throw new ObjectNotFoundException("No user specified");
1729 List<FileHeader> files = dao.getSharedFiles(userId);
1730 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1731 for (FileHeader f : files)
1732 result.add(f.getDTO());
1737 public List<FolderDTO> getSharedFolders(Long userId) throws ObjectNotFoundException {
1739 throw new ObjectNotFoundException("No user specified");
1740 List<Folder> folders = dao.getSharedFolders(userId);
1741 List<FolderDTO> result = new ArrayList<FolderDTO>();
1742 for (Folder f : folders)
1743 result.add(f.getDTO());
1748 * @see gr.ebs.gss.server.ejb.ExternalAPI#getSharedFiles(java.lang.Long, java.lang.Long)
1751 public List<FileHeaderDTO> getSharedFiles(Long ownerId, Long callingUserId) throws ObjectNotFoundException {
1752 if (ownerId == null)
1753 throw new ObjectNotFoundException("No owner specified");
1754 if (callingUserId == null)
1755 throw new ObjectNotFoundException("No calling user specified");
1756 List<FileHeader> folders = dao.getSharedFiles(ownerId, callingUserId);
1757 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1758 for (FileHeader f : folders)
1759 result.add(f.getDTO());
1764 public List<FolderDTO> getSharedRootFolders(Long ownerId, Long callingUserId) throws ObjectNotFoundException {
1765 if (ownerId == null)
1766 throw new ObjectNotFoundException("No owner specified");
1767 if (callingUserId == null)
1768 throw new ObjectNotFoundException("No calling user specified");
1769 List<Folder> folders = dao.getSharedRootFolders(ownerId, callingUserId);
1770 List<FolderDTO> result = new ArrayList<FolderDTO>();
1771 for (Folder f : folders) {
1772 FolderDTO dto = f.getDTO();
1773 dto.setSubfolders(getSharedSubfolders(ownerId, callingUserId, f.getId()));
1781 public List<FolderDTO> getSharedSubfolders(Long userId, Long folderId) throws ObjectNotFoundException {
1783 throw new ObjectNotFoundException("No user specified");
1784 if (folderId == null)
1785 throw new ObjectNotFoundException("No folder specified");
1786 User user = dao.getEntityById(User.class, userId);
1787 Folder folder = dao.getEntityById(Folder.class, folderId);
1788 List<FolderDTO> result = new ArrayList<FolderDTO>();
1789 if (folder.isShared(user))
1790 for (Folder f : folder.getSubfolders())
1791 if (f.isShared(user) && !f.isDeleted())
1792 result.add(f.getDTO());
1797 public List<FolderDTO> getSharedSubfolders(Long userId, Long callingUserId, Long folderId) throws ObjectNotFoundException {
1799 throw new ObjectNotFoundException("No user specified");
1800 if (callingUserId == null)
1801 throw new ObjectNotFoundException("No user specified");
1802 if (folderId == null)
1803 throw new ObjectNotFoundException("No folder specified");
1804 User user = dao.getEntityById(User.class, callingUserId);
1805 Folder folder = dao.getEntityById(Folder.class, folderId);
1806 List<FolderDTO> result = new ArrayList<FolderDTO>();
1807 if (folder.isSharedForOtherUser(user))
1808 for (Folder f : folder.getSubfolders())
1809 if (f.isSharedForOtherUser(user) && !f.isDeleted()){
1810 FolderDTO dto = f.getDTO();
1811 dto.setSubfolders(getSharedSubfolders(userId, callingUserId, dto.getId()));
1819 * @see gr.ebs.gss.server.ejb.ExternalAPI#searchFiles(java.lang.Long, java.lang.String)
1822 public List<FileHeaderDTO> searchFiles(Long userId, String query) throws ObjectNotFoundException {
1824 throw new ObjectNotFoundException("No user specified");
1825 User user = getUser(userId);
1827 throw new ObjectNotFoundException("No query specified");
1828 List<FileHeader> files = search(user.getId(), query);
1829 List<FileHeaderDTO> res = new ArrayList<FileHeaderDTO>();
1830 for(FileHeader f : files)
1831 res.add(f.getDTO());
1836 * Performs the actuals search on the solr server and returns the results
1838 * We have to use the dismax query type (instead of the
1839 * standard) because it allows for search time field boosting. This is because we can't use indexing
1840 * time field boosting due to the patched rich indexing API that does not allow it
1844 * @return a List of FileHeader objects
1846 private List<FileHeader> search(Long userId, String query) {
1848 HttpClient httpClient = new HttpClient();
1850 GetMethod method = new GetMethod(getConfiguration().getString("solrSelectUrl"));
1851 NameValuePair[] params = {new NameValuePair("qt", "dismax"),
1852 new NameValuePair("q", query),
1853 new NameValuePair("sort", "score desc"),
1854 new NameValuePair("indent", "on")};
1855 method.setQueryString(params);
1858 String response = null;
1860 statusCode = httpClient.executeMethod(method);
1861 logger.debug("HTTP status: " + statusCode);
1862 response = method.getResponseBodyAsString();
1863 logger.debug(response);
1865 if (statusCode != 200 && retryCount < 3)
1867 Thread.sleep(3000); //Give Solr a little time to be available
1868 } catch (InterruptedException e) {
1870 } while (statusCode != 200 && retryCount < 3);
1871 if (statusCode != 200)
1872 throw new EJBException("Search query return error:\n" + response);
1874 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
1875 DocumentBuilder db = dbf.newDocumentBuilder();
1876 Document doc = db.parse(method.getResponseBodyAsStream());
1877 method.releaseConnection();
1879 Node root = doc.getElementsByTagName("response").item(0);
1880 Node lst = root.getFirstChild().getNextSibling();
1881 Node status = lst.getFirstChild().getNextSibling();
1882 if (status.getAttributes().getNamedItem("name").getNodeValue().equals("status") &&
1883 status.getTextContent().equals("0")) {
1884 List<FileHeader> fileResult = new ArrayList<FileHeader>();
1885 Node result = lst.getNextSibling().getNextSibling();
1886 NodeList docs = result.getChildNodes();
1887 User user = getUser(userId);
1888 for (int i=1; i<docs.getLength(); i=i+2) {
1889 Node d = docs.item(i);
1890 NodeList docData = d.getChildNodes();
1891 for (int j=1; j<docData.getLength(); j=j+2) {
1892 Node dd = docData.item(j);
1893 if (dd.getAttributes().item(0).getNodeName().equals("name") &&
1894 dd.getAttributes().item(0).getNodeValue().equals("id")) {
1895 Long fileId = Long.valueOf(dd.getTextContent());
1897 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1898 if (file.hasReadPermission(user)) {
1899 fileResult.add(file);
1900 logger.debug("File added " + fileId);
1902 } catch (ObjectNotFoundException e) {
1903 logger.warn("Search result not found", e);
1910 throw new EJBException();
1911 } catch (HttpException e) {
1912 throw new EJBException(e);
1913 } catch (IOException e) {
1914 throw new EJBException(e);
1915 } catch (SAXException e) {
1916 throw new EJBException(e);
1917 } catch (ParserConfigurationException e) {
1918 throw new EJBException(e);
1919 } catch (ObjectNotFoundException e) {
1920 throw new EJBException(e);
1925 * @see gr.ebs.gss.server.ejb.ExternalAPI#copyFiles(java.lang.Long, java.util.List, java.lang.Long)
1928 public void copyFiles(Long userId, List<Long> fileIds, Long destId) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
1929 for(Long l : fileIds){
1930 FileHeader file = dao.getEntityById(FileHeader.class, l);
1931 copyFile(userId, l, destId, file.getName());
1938 * @see gr.ebs.gss.server.ejb.ExternalAPI#moveFiles(java.lang.Long, java.util.List, java.lang.Long)
1941 public void moveFiles(Long userId, List<Long> fileIds, Long destId) throws InsufficientPermissionsException, ObjectNotFoundException, QuotaExceededException {
1942 for(Long l : fileIds){
1943 FileHeader file = dao.getEntityById(FileHeader.class, l);
1944 moveFile(userId, l, destId, file.getName());
1950 * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteFiles(java.lang.Long, java.util.List)
1953 public void deleteFiles(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1955 throw new ObjectNotFoundException("No user specified");
1956 final User user = dao.getEntityById(User.class, userId);
1957 List<String> filesToRemove = new ArrayList<String>();
1958 //first delete database objects
1959 for(Long fileId : fileIds){
1961 throw new ObjectNotFoundException("No file specified");
1962 final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1963 final Folder parent = file.getFolder();
1965 throw new ObjectNotFoundException("The specified file has no parent folder");
1966 if (!file.hasDeletePermission(user))
1967 throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
1969 parent.removeFile(file);
1970 for (final FileBody body : file.getBodies())
1971 filesToRemove.add(body.getStoredFilePath());
1973 touchParentFolders(parent, user, new Date());
1975 //then remove physical files if everything is ok
1976 for(String physicalFileName : filesToRemove)
1977 deleteActualFile(physicalFileName);
1978 //then unindex deleted files
1979 for(Long fileId : fileIds)
1980 indexFile(fileId, true);
1985 * @see gr.ebs.gss.server.ejb.ExternalAPI#moveFilesToTrash(java.lang.Long, java.util.List)
1988 public void moveFilesToTrash(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1989 for(Long l : fileIds)
1990 moveFileToTrash(userId, l);
1995 public void removeFilesFromTrash(Long userId, List<Long> fileIds) throws ObjectNotFoundException, InsufficientPermissionsException {
1996 for(Long l : fileIds)
1997 removeFileFromTrash(userId, l);
2002 public Nonce createNonce(Long userId) throws ObjectNotFoundException {
2004 throw new ObjectNotFoundException("No user specified");
2005 User user = dao.getEntityById(User.class, userId);
2006 Nonce nonce = Nonce.createNonce(user.getId());
2012 public Nonce getNonce(String nonce, Long userId) throws ObjectNotFoundException {
2014 throw new ObjectNotFoundException("No user specified");
2016 throw new ObjectNotFoundException("No nonce specified");
2017 return dao.getNonce(nonce, userId);
2021 public void removeNonce(Long id) throws ObjectNotFoundException {
2023 throw new ObjectNotFoundException("No nonce specified");
2024 Nonce nonce = dao.getEntityById(Nonce.class, id);
2029 public void activateUserNonce(Long userId, String nonce, Date nonceExpiryDate) throws ObjectNotFoundException {
2031 throw new ObjectNotFoundException("No user specified");
2032 User user = dao.getEntityById(User.class, userId);
2033 user.setNonce(nonce);
2034 user.setNonceExpiryDate(nonceExpiryDate);
2038 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUserStatistics(java.lang.Long)
2041 public StatsDTO getUserStatistics(Long userId) throws ObjectNotFoundException {
2043 throw new ObjectNotFoundException("No user specified");
2044 StatsDTO stats = new StatsDTO();
2045 stats.setFileCount(dao.getFileCount(userId));
2046 Long fileSize = dao.getFileSize(userId);
2047 stats.setFileSize(fileSize);
2048 Long quota = getQuota(userId);
2049 Long quotaLeft = quota - fileSize;
2050 stats.setQuotaLeftSize(quotaLeft);
2055 * @see gr.ebs.gss.server.ejb.ExternalAPI#getVersions(java.lang.Long, java.lang.Long)
2058 public List<FileBodyDTO> getVersions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
2060 throw new ObjectNotFoundException("No user specified");
2062 throw new ObjectNotFoundException("No file specified");
2063 User user = dao.getEntityById(User.class, userId);
2064 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
2065 if(!header.hasReadPermission(user))
2066 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2067 List<FileBodyDTO> result = new LinkedList<FileBodyDTO>();
2068 for(int i = header.getBodies().size()-1 ; i>=0; i--)
2069 result.add(header.getBodies().get(i).getDTO());
2074 * @see gr.ebs.gss.server.ejb.ExternalAPI#removeVersion(java.lang.Long, java.lang.Long, java.lang.Long)
2077 public void removeVersion(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
2079 throw new ObjectNotFoundException("No user specified");
2081 throw new ObjectNotFoundException("No file specified");
2083 throw new ObjectNotFoundException("No body specified");
2084 User user = dao.getEntityById(User.class, userId);
2085 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
2086 if(!header.hasWritePermission(user))
2087 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2088 FileBody body = dao.getEntityById(FileBody.class, bodyId);
2089 if(body.equals(header.getCurrentBody())){
2091 if(header.getBodies().size() == 1)
2092 throw new InsufficientPermissionsException("You cant delete this version, Delete file instead!");
2093 for(FileBody b : header.getBodies())
2094 if(b.getVersion() == body.getVersion()-1)
2095 header.setCurrentBody(b);
2097 deleteActualFile(body.getStoredFilePath());
2098 header.getBodies().remove(body);
2100 Folder parent = header.getFolder();
2101 touchParentFolders(parent, user, new Date());
2106 public void restoreVersion(Long userId, Long fileId, int version) throws ObjectNotFoundException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
2108 throw new ObjectNotFoundException("No user specified");
2110 throw new ObjectNotFoundException("No file specified");
2111 User user = dao.getEntityById(User.class, userId);
2112 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
2113 if(!header.hasWritePermission(user))
2114 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2115 FileBody body = dao.getFileVersion(fileId, version);
2116 final File fileContents = new File(body.getStoredFilePath());
2119 updateFileContents(userId, fileId, body.getMimeType(), new FileInputStream(fileContents) );
2120 } catch (FileNotFoundException e) {
2121 throw new GSSIOException(e);
2127 * @see gr.ebs.gss.server.ejb.ExternalAPI#removeOldVersions(java.lang.Long, java.lang.Long)
2130 public void removeOldVersions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
2132 throw new ObjectNotFoundException("No user specified");
2134 throw new ObjectNotFoundException("No file specified");
2135 User user = dao.getEntityById(User.class, userId);
2136 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
2137 if(!header.hasWritePermission(user))
2138 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2139 Iterator<FileBody> it = header.getBodies().iterator();
2140 while(it.hasNext()){
2141 FileBody body = it.next();
2142 if(!body.equals(header.getCurrentBody())){
2143 deleteActualFile(body.getStoredFilePath());
2148 header.getCurrentBody().setVersion(1);
2150 Folder parent = header.getFolder();
2151 touchParentFolders(parent, user, new Date());
2155 * Gets the quota left for specified user ID.
2157 private Long getQuotaLeft(Long userId) throws ObjectNotFoundException{
2158 Long fileSize = dao.getFileSize(userId);
2159 Long quota = getQuota(userId);
2160 return quota - fileSize;
2164 * Gets the quota for specified user ID.
2166 private Long getQuota(Long userId) throws ObjectNotFoundException{
2167 return getUser(userId).getUserClass().getQuota();
2170 public void rebuildSolrIndex() {
2171 MessageProducer sender = null;
2172 Session session = null;
2173 Connection qConn = null;
2175 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
2176 DocumentBuilder db = dbf.newDocumentBuilder();
2177 Document doc = db.newDocument();
2178 Node root = doc.createElement("delete");
2179 doc.appendChild(root);
2180 Node queryNode = doc.createElement("query");
2181 root.appendChild(queryNode);
2182 queryNode.appendChild(doc.createTextNode("*:*"));
2184 TransformerFactory fact = TransformerFactory.newInstance();
2185 Transformer trans = fact.newTransformer();
2186 trans.setOutputProperty(OutputKeys.INDENT, "yes");
2187 StringWriter sw = new StringWriter();
2188 StreamResult sr = new StreamResult(sw);
2189 DOMSource source = new DOMSource(doc);
2190 trans.transform(source, sr);
2191 logger.debug(sw.toString());
2193 HttpClient httpClient = new HttpClient();
2194 PostMethod method = new PostMethod(getConfiguration().getString("solrUpdateUrl"));
2195 method.setRequestEntity(new StringRequestEntity(sw.toString()));
2198 String response = null;
2200 statusCode = httpClient.executeMethod(method);
2201 logger.debug("HTTP status: " + statusCode);
2202 response = method.getResponseBodyAsString();
2203 logger.debug(response);
2205 if (statusCode != 200 && retryCount < 3)
2207 Thread.sleep(10000); //Give Solr a little time to be available
2208 } catch (InterruptedException e) {
2210 } while (statusCode != 200 && retryCount < 3);
2211 method.releaseConnection();
2212 if (statusCode != 200)
2213 throw new EJBException("Cannot clear Solr index. Solr response is:\n" + response);
2214 List<Long> fileIds = dao.getAllFileIds();
2216 Context jndiCtx = new InitialContext();
2217 ConnectionFactory factory = (QueueConnectionFactory) jndiCtx.lookup("java:/JmsXA");
2218 Queue queue = (Queue) jndiCtx.lookup("queue/gss-indexingQueue");
2219 qConn = factory.createConnection();
2220 session = qConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
2221 sender = session.createProducer(queue);
2223 for (Long id : fileIds) {
2224 MapMessage map = session.createMapMessage();
2225 map.setObject("id", id);
2226 map.setBoolean("delete", false);
2229 sendOptimize(httpClient, 0);
2230 } catch (DOMException e) {
2231 throw new EJBException(e);
2232 } catch (TransformerConfigurationException e) {
2233 throw new EJBException(e);
2234 } catch (IllegalArgumentException e) {
2235 throw new EJBException(e);
2236 } catch (HttpException e) {
2237 throw new EJBException(e);
2238 } catch (UnsupportedEncodingException e) {
2239 throw new EJBException(e);
2240 } catch (ParserConfigurationException e) {
2241 throw new EJBException(e);
2242 } catch (TransformerException e) {
2243 throw new EJBException(e);
2244 } catch (IOException e) {
2245 throw new EJBException(e);
2246 } catch (NamingException e) {
2247 throw new EJBException(e);
2248 } catch (JMSException e) {
2249 throw new EJBException(e);
2255 if (session != null)
2260 catch (JMSException e) {
2267 * Sends a optimize message to the solr server
2270 * @param retryCount If the commit fails, it is retried three times. This parameter is passed in the recursive
2271 * calls to stop the recursion
2272 * @throws UnsupportedEncodingException
2273 * @throws IOException
2274 * @throws HttpException
2276 private void sendOptimize(HttpClient httpClient, int retryCount) throws UnsupportedEncodingException, IOException, HttpException {
2277 PostMethod method = null;
2279 logger.debug("Optimize retry: " + retryCount);
2280 method = new PostMethod(getConfiguration().getString("solrUpdateUrl"));
2281 method.setRequestEntity(new StringRequestEntity("<optimize/>", "text/xml", "iso8859-1"));
2282 int statusCode = httpClient.executeMethod(method);
2283 logger.debug("HTTP status: " + statusCode);
2284 String response = method.getResponseBodyAsString();
2285 logger.debug(response);
2286 if (statusCode != 200 && retryCount < 2) {
2288 Thread.sleep(10000); //Give Solr a little time to be available
2289 } catch (InterruptedException e) {
2291 sendOptimize(httpClient, retryCount + 1);
2296 method.releaseConnection();
2300 public FileHeaderDTO createFile(Long userId, Long folderId, String name, String mimeType, long fileSize, String filePath)
2301 throws DuplicateNameException, ObjectNotFoundException, GSSIOException,
2302 InsufficientPermissionsException, QuotaExceededException {
2305 throw new ObjectNotFoundException("No user specified");
2306 if (folderId == null)
2307 throw new ObjectNotFoundException("No folder specified");
2308 String contentType = mimeType;
2309 if (StringUtils.isEmpty(mimeType))
2310 contentType = DEFAULT_MIME_TYPE;
2311 if (StringUtils.isEmpty(name))
2312 throw new ObjectNotFoundException("No file name specified");
2313 if (dao.existsFolderOrFile(folderId, name))
2314 throw new DuplicateNameException("A folder or file with the name '" + name +
2315 "' already exists at this level");
2317 // Do the actual work.
2318 Folder parent = null;
2320 parent = dao.getEntityById(Folder.class, folderId);
2321 } catch (final ObjectNotFoundException onfe) {
2322 // Supply a more accurate problem description.
2323 throw new ObjectNotFoundException("Parent folder not found");
2325 final User owner = dao.getEntityById(User.class, userId);
2326 if (!parent.hasWritePermission(owner))
2327 throw new InsufficientPermissionsException("You don't have the permissions to write to this folder");
2328 final FileHeader file = new FileHeader();
2330 parent.addFile(file);
2331 // set file owner to folder owner
2332 file.setOwner(parent.getOwner());
2334 final Date now = new Date();
2335 final AuditInfo auditInfo = new AuditInfo();
2336 auditInfo.setCreatedBy(owner);
2337 auditInfo.setCreationDate(now);
2338 auditInfo.setModifiedBy(owner);
2339 auditInfo.setModificationDate(now);
2340 file.setAuditInfo(auditInfo);
2341 // TODO set the proper versioning flag on creation
2342 file.setVersioned(false);
2344 for (final Permission p : parent.getPermissions()) {
2345 final Permission permission = new Permission();
2346 permission.setGroup(p.getGroup());
2347 permission.setUser(p.getUser());
2348 permission.setRead(p.getRead());
2349 permission.setWrite(p.getWrite());
2350 permission.setModifyACL(p.getModifyACL());
2351 file.addPermission(permission);
2354 // Create the file body.
2356 createFileBody(name, contentType, fileSize, filePath, file, auditInfo);
2357 } catch (FileNotFoundException e) {
2358 throw new GSSIOException(e);
2360 touchParentFolders(parent, owner, new Date());
2362 indexFile(file.getId(), false);
2364 return file.getDTO();
2368 * @see gr.ebs.gss.server.ejb.ExternalAPI#updateFileContents(java.lang.Long, java.lang.Long, java.lang.String, java.io.InputStream)
2370 public FileHeaderDTO updateFileContents(Long userId, Long fileId, String mimeType, long fileSize, String filePath) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
2372 throw new ObjectNotFoundException("No user specified");
2374 throw new ObjectNotFoundException("No file specified");
2375 String contentType = mimeType;
2377 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
2379 // if no mime type or the generic mime type is defined by the client, then try to identify it from the filename extension
2380 if (StringUtils.isEmpty(mimeType) || "application/octet-stream".equals(mimeType)
2381 || "application/download".equals(mimeType) || "application/force-download".equals(mimeType)
2382 || "octet/stream".equals(mimeType) || "application/unknown".equals(mimeType))
2383 contentType = identifyMimeType(file.getName());
2385 final User owner = dao.getEntityById(User.class, userId);
2386 if (!file.hasWritePermission(owner))
2387 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2388 final Date now = new Date();
2389 final AuditInfo auditInfo = new AuditInfo();
2390 auditInfo.setCreatedBy(owner);
2391 auditInfo.setCreationDate(now);
2392 auditInfo.setModifiedBy(owner);
2393 auditInfo.setModificationDate(now);
2395 createFileBody(file.getName(), contentType, fileSize, filePath, file, auditInfo);
2396 } catch (FileNotFoundException e) {
2397 throw new GSSIOException(e);
2399 Folder parent = file.getFolder();
2400 touchParentFolders(parent, owner, new Date());
2402 indexFile(fileId, false);
2403 return file.getDTO();
2407 * Helper method for identifying mime type by examining the filename extension
2410 * @return the mime type
2412 private String identifyMimeType(String filename) {
2413 if (filename.indexOf('.') != -1) {
2414 String extension = filename.substring(filename.lastIndexOf('.')).toLowerCase(Locale.ENGLISH);
2415 if (".doc".equals(extension))
2416 return "application/msword";
2417 else if (".xls".equals(extension))
2418 return "application/vnd.ms-excel";
2419 else if (".ppt".equals(extension))
2420 return "application/vnd.ms-powerpoint";
2421 else if (".pdf".equals(extension))
2422 return "application/pdf";
2423 else if (".gif".equals(extension))
2425 else if (".jpg".equals(extension) || ".jpeg".equals(extension) || ".jpe".equals(extension))
2426 return "image/jpeg";
2427 else if (".tiff".equals(extension) || ".tif".equals(extension))
2428 return "image/tiff";
2429 else if (".png".equals(extension))
2431 else if (".bmp".equals(extension))
2434 // when all else fails assign the default mime type
2435 return DEFAULT_MIME_TYPE;
2439 * Helper method to create a new file body and attach it as the current body
2440 * of the provided file header.
2442 * @param name the original file name
2443 * @param mimeType the content type
2444 * @param fileSize the uploaded file size
2445 * @param filePath the uploaded file full path
2446 * @param header the file header that will be associated with the new body
2447 * @param auditInfo the audit info
2448 * @param owner the owner of the file
2449 * @throws FileNotFoundException
2450 * @throws QuotaExceededException
2451 * @throws ObjectNotFoundException if the owner was not found
2453 private void createFileBody(String name, String mimeType, long fileSize, String filePath,
2454 FileHeader header, AuditInfo auditInfo)
2455 throws FileNotFoundException, QuotaExceededException, ObjectNotFoundException {
2457 long currentTotalSize = 0;
2458 if (!header.isVersioned() && header.getCurrentBody() != null && header.getBodies() != null)
2459 currentTotalSize = header.getTotalSize();
2460 Long quotaLeft = getQuotaLeft(header.getOwner().getId());
2461 if(quotaLeft < fileSize-currentTotalSize) {
2462 // quota exceeded -> delete the file
2463 deleteActualFile(filePath);
2464 throw new QuotaExceededException("Not enough free space available");
2467 FileBody body = new FileBody();
2469 // if no mime type or the generic mime type is defined by the client, then try to identify it from the filename extension
2470 if (StringUtils.isEmpty(mimeType) || "application/octet-stream".equals(mimeType)
2471 || "application/download".equals(mimeType) || "application/force-download".equals(mimeType)
2472 || "octet/stream".equals(mimeType) || "application/unknown".equals(mimeType))
2473 body.setMimeType(identifyMimeType(name));
2475 body.setMimeType(mimeType);
2476 body.setAuditInfo(auditInfo);
2477 body.setFileSize(fileSize);
2478 body.setOriginalFilename(name);
2479 body.setStoredFilePath(filePath);
2480 //CLEAR OLD VERSION IF FILE IS NOT VERSIONED AND GETS UPDATED
2481 if(!header.isVersioned() && header.getCurrentBody() != null){
2482 header.setCurrentBody(null);
2483 if (header.getBodies() != null) {
2484 Iterator<FileBody> it = header.getBodies().iterator();
2485 while(it.hasNext()){
2486 FileBody bo = it.next();
2487 deleteActualFile(bo.getStoredFilePath());
2495 header.addBody(body);
2496 header.setAuditInfo(auditInfo);
2502 @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
2503 public File uploadFile(InputStream stream, Long userId) throws IOException, ObjectNotFoundException {
2505 throw new ObjectNotFoundException("No user specified");
2506 User owner = dao.getEntityById(User.class, userId);
2508 throw new ObjectNotFoundException("No user specified");
2509 long start = 0, end = 0;
2510 if (logger.isDebugEnabled())
2511 start = System.currentTimeMillis();
2512 File result = new File(generateRepositoryFilePath());
2514 final FileOutputStream output = new FileOutputStream(result);
2515 final byte[] buffer = new byte[UPLOAD_BUFFER_SIZE];
2518 while (-1 != (n = stream.read(buffer)))
2519 output.write(buffer, 0, n);
2522 } catch (IOException e) {
2523 if (!result.delete())
2524 logger.warn("Could not delete " + result.getPath());
2527 if (logger.isDebugEnabled()) {
2528 end = System.currentTimeMillis();
2529 logger.debug("Time to upload: " + (end - start) + " (msec)");
2535 public void createFileUploadProgress(Long userId, String filename, Long bytesTransfered, Long fileSize) throws ObjectNotFoundException{
2538 throw new ObjectNotFoundException("No user specified");
2539 User user = dao.getEntityById(User.class, userId);
2540 FileUploadStatus status = dao.getFileUploadStatus(userId, filename);
2542 status = new FileUploadStatus();
2543 status.setOwner(user);
2544 status.setFilename(filename);
2545 status.setBytesUploaded(bytesTransfered);
2546 status.setFileSize(fileSize);
2550 status.setBytesUploaded(bytesTransfered);
2551 status.setFileSize(fileSize);
2557 public void removeFileUploadProgress(Long userId, String filename) throws ObjectNotFoundException{
2559 throw new ObjectNotFoundException("No user specified");
2560 FileUploadStatus status = dao.getFileUploadStatus(userId, filename);
2566 public FileUploadStatus getFileUploadStatus(Long userId, String fileName) {
2567 return dao.getFileUploadStatus(userId, fileName);
2571 public FolderDTO getFolderWithSubfolders(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
2573 throw new ObjectNotFoundException("No user specified");
2574 if (folderId == null)
2575 throw new ObjectNotFoundException("No folder specified");
2576 final User user = dao.getEntityById(User.class, userId);
2577 final Folder folder = dao.getEntityById(Folder.class, folderId);
2578 // Check permissions
2579 if (!folder.hasReadPermission(user))
2580 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
2581 List<FolderDTO> subfolders = new ArrayList<FolderDTO>();
2582 if (folder.hasReadPermission(user))
2583 for (Folder f : folder.getSubfolders())
2584 if (f.hasReadPermission(user) && !f.isDeleted())
2585 subfolders.add(f.getDTO());
2586 FolderDTO result = folder.getDTO();
2587 result.setSubfolders(subfolders);
2588 return folder.getDTO();
2592 public FolderDTO getFolderWithSubfolders(Long userId, Long callingUserId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
2594 throw new ObjectNotFoundException("No user specified");
2595 if (folderId == null)
2596 throw new ObjectNotFoundException("No folder specified");
2597 User user = dao.getEntityById(User.class, callingUserId);
2598 Folder folder = dao.getEntityById(Folder.class, folderId);
2599 // Check permissions
2600 if (!folder.hasReadPermission(user))
2601 throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
2603 FolderDTO result = folder.getDTO();
2604 result.setSubfolders(getSharedSubfolders(userId, callingUserId, folder.getId()));
2609 public FileBodyDTO getFileVersion(Long userId, Long fileId, int version)
2610 throws ObjectNotFoundException, InsufficientPermissionsException {
2612 throw new ObjectNotFoundException("No user specified");
2614 throw new ObjectNotFoundException("No file specified");
2616 throw new ObjectNotFoundException("No valid version specified");
2617 User user = dao.getEntityById(User.class, userId);
2618 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
2619 if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
2620 throw new InsufficientPermissionsException("You don't have the necessary permissions");
2621 FileBody body = dao.getFileVersion(fileId, version);
2622 return body.getDTO();
2626 public User updateUserPolicyAcceptance(Long userId, boolean isAccepted) throws ObjectNotFoundException {
2628 throw new ObjectNotFoundException("No user specified");
2629 User user = dao.getEntityById(User.class, userId);
2630 user.setAcceptedPolicy(isAccepted);
2635 public void updateAccounting(User user, Date date, long bandwidthDiff) {
2636 dao.updateAccounting(user, date, bandwidthDiff);
2640 public boolean canReadFolder(Long userId, Long folderId) throws ObjectNotFoundException {
2642 throw new ObjectNotFoundException("No user specified");
2643 if (folderId == null)
2644 throw new ObjectNotFoundException("No folder specified");
2645 User user = dao.getEntityById(User.class, userId);
2646 Folder folder = dao.getEntityById(Folder.class, folderId);
2647 // Check permissions
2648 if (!folder.hasReadPermission(user))
2654 public String resetWebDAVPassword(Long userId) throws ObjectNotFoundException {
2656 throw new ObjectNotFoundException("No user specified");
2657 User user = dao.getEntityById(User.class, userId);
2658 user.generateWebDAVPassword();
2659 return user.getWebDAVPassword();
2663 public Invitation findInvite(String code) {
2666 return dao.findInvite(code);
2670 public void createLdapUser(String username, String firstname, String lastname, String email, String password) {
2671 LDAPConnection lc = new LDAPConnection();
2672 LDAPAttributeSet attributeSet = new LDAPAttributeSet();
2673 attributeSet.add(new LDAPAttribute("objectClass", getConfiguration().getStringArray("objectClass")));
2674 attributeSet.add(new LDAPAttribute("uid", username));
2675 attributeSet.add(new LDAPAttribute("cn", new String[]{firstname + " " + lastname}));
2676 attributeSet.add(new LDAPAttribute("sn", lastname));
2677 attributeSet.add(new LDAPAttribute("givenName", firstname));
2678 attributeSet.add(new LDAPAttribute("mail", email));
2679 attributeSet.add(new LDAPAttribute("userPassword", password));
2680 String dn = "uid=" + username + "," + getConfiguration().getString("baseDn");
2681 LDAPEntry newEntry = new LDAPEntry(dn, attributeSet);
2683 lc.connect(getConfiguration().getString("ldapHost"), LDAPConnection.DEFAULT_PORT);
2684 lc.bind(LDAPConnection.LDAP_V3, getConfiguration().getString("bindDn"),
2685 getConfiguration().getString("bindPassword").getBytes("UTF8"));
2687 logger.info("Successfully added LDAP account: " + dn);
2689 } catch(LDAPException e) {
2690 throw new RuntimeException(e);
2691 } catch(UnsupportedEncodingException e) {
2692 throw new RuntimeException(e);
2698 public UserClass upgradeUserClass(String username, String code) throws ObjectNotFoundException, InvitationUsedException {
2699 User user = findUser(username);
2701 throw new ObjectNotFoundException("The user was not found");
2702 Invitation invite = findInvite(code);
2703 if (invite.getUser() != null)
2704 throw new InvitationUsedException("This code has already been used");
2705 invite.setUser(user);
2706 UserClass couponClass = getCouponUserClass();
2707 user.setUserClass(couponClass);
2712 public UserClass getCouponUserClass() {
2713 return dao.findCouponUserClass();