X-Git-Url: https://code.grnet.gr/git/pithos/blobdiff_plain/125c5690705bcb788e18e523a4d6b4872e00fc8b..c4a1323760135e13d4a41e4bc80371056919f510:/src/gr/ebs/gss/server/ejb/ExternalAPIBean.java diff --git a/src/gr/ebs/gss/server/ejb/ExternalAPIBean.java b/src/gr/ebs/gss/server/ejb/ExternalAPIBean.java index fa265e5..88059a0 100644 --- a/src/gr/ebs/gss/server/ejb/ExternalAPIBean.java +++ b/src/gr/ebs/gss/server/ejb/ExternalAPIBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2007, 2008, 2009 Electronic Business Systems Ltd. + * Copyright 2007, 2008, 2009, 2010 Electronic Business Systems Ltd. * * This file is part of GSS. * @@ -19,9 +19,12 @@ package gr.ebs.gss.server.ejb; import static gr.ebs.gss.server.configuration.GSSConfigurationFactory.getConfiguration; + +import gr.ebs.gss.admin.client.ui.UsersTable; import gr.ebs.gss.client.exceptions.DuplicateNameException; import gr.ebs.gss.client.exceptions.GSSIOException; import gr.ebs.gss.client.exceptions.InsufficientPermissionsException; +import gr.ebs.gss.client.exceptions.InvitationUsedException; import gr.ebs.gss.client.exceptions.ObjectNotFoundException; import gr.ebs.gss.client.exceptions.QuotaExceededException; import gr.ebs.gss.server.domain.AuditInfo; @@ -31,14 +34,14 @@ import gr.ebs.gss.server.domain.FileTag; import gr.ebs.gss.server.domain.FileUploadStatus; import gr.ebs.gss.server.domain.Folder; import gr.ebs.gss.server.domain.Group; +import gr.ebs.gss.server.domain.FileLock; +import gr.ebs.gss.server.domain.Invitation; import gr.ebs.gss.server.domain.Nonce; import gr.ebs.gss.server.domain.Permission; import gr.ebs.gss.server.domain.User; -import gr.ebs.gss.server.domain.dto.FileBodyDTO; -import gr.ebs.gss.server.domain.dto.FileHeaderDTO; -import gr.ebs.gss.server.domain.dto.FolderDTO; -import gr.ebs.gss.server.domain.dto.GroupDTO; -import gr.ebs.gss.server.domain.dto.PermissionDTO; +import gr.ebs.gss.server.domain.UserClass; +import gr.ebs.gss.server.domain.UserLogin; +import gr.ebs.gss.server.domain.WebDavNonce; import gr.ebs.gss.server.domain.dto.StatsDTO; import gr.ebs.gss.server.domain.dto.UserDTO; @@ -48,13 +51,12 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.StringWriter; import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.LinkedHashSet; -import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Random; @@ -79,32 +81,26 @@ import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.persistence.PersistenceException; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerConfigurationException; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpException; -import org.apache.commons.httpclient.NameValuePair; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.commons.httpclient.methods.PostMethod; -import org.apache.commons.httpclient.methods.StringRequestEntity; + import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.solr.client.solrj.SolrQuery; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer; +import org.apache.solr.client.solrj.request.ContentStreamUpdateRequest; +import org.apache.solr.client.solrj.response.QueryResponse; +import org.apache.solr.common.SolrDocument; +import org.apache.solr.common.SolrDocumentList; +import org.apache.solr.common.SolrException; +import org.apache.solr.common.SolrInputDocument; import org.hibernate.exception.ConstraintViolationException; -import org.w3c.dom.DOMException; -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; + +import com.novell.ldap.LDAPAttribute; +import com.novell.ldap.LDAPAttributeSet; +import com.novell.ldap.LDAPConnection; +import com.novell.ldap.LDAPEntry; +import com.novell.ldap.LDAPException; /** * The concrete implementation of the ExternalAPI interface. @@ -141,31 +137,36 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { */ private static Random random = new Random(); - private void touchParentFolders(Folder folder, User modifiedBy, Date modificationDate) { + /** + * Mark the folder and all of its parent folders as modified from the specified user. + */ + private void touchParentFolders(Folder folder, User user, Date date) { Folder f = folder; - while (f!=null) { + while (f != null) { AuditInfo ai = f.getAuditInfo(); - ai.setModifiedBy(modifiedBy); - ai.setModificationDate(modificationDate); + ai.setModifiedBy(user); + ai.setModificationDate(date); f.setAuditInfo(ai); f = f.getParent(); } } + private Long getRootFolderId(Long userId) throws ObjectNotFoundException { + if (userId == null) + throw new ObjectNotFoundException("No user specified"); + return dao.getRootFolderId(userId); + } + @Override - public FolderDTO getRootFolder(Long userId) throws ObjectNotFoundException { + public Folder getRootFolder(Long userId) throws ObjectNotFoundException { if (userId == null) throw new ObjectNotFoundException("No user specified"); Folder folder = dao.getRootFolder(userId); - return folder.getDTO(); + return folder; } - /* - * (non-Javadoc) - * - * @see gr.ebs.gss.server.ejb.ExternalAPI#getFolder(java.lang.Long) - */ - public FolderDTO getFolder(final Long userId, final Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException { + @Override + public Folder getFolder(final Long userId, final Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException { if (userId == null) throw new ObjectNotFoundException("No user specified"); if (folderId == null) @@ -175,39 +176,31 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { // Check permissions if (!folder.hasReadPermission(user)) throw new InsufficientPermissionsException("You don't have the permissions to read this folder"); - return folder.getDTO(); + return expandFolder(folder); } - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#getUser(java.lang.Long) - */ + @Override public User getUser(Long userId) throws ObjectNotFoundException { if (userId == null) throw new ObjectNotFoundException("No user specified"); return dao.getEntityById(User.class, userId); } - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#getUserDTO(java.lang.Long) - */ + @Override public UserDTO getUserDTO(final Long userId) throws ObjectNotFoundException { return getUser(userId).getDTO(); } - /* - * (non-Javadoc) - * - * @see gr.ebs.gss.server.ejb.ExternalAPI#getGroup(java.lang.Long) - */ - public GroupDTO getGroup(final Long groupId) throws ObjectNotFoundException { + @Override + public Group getGroup(final Long groupId) throws ObjectNotFoundException { if (groupId == null) throw new ObjectNotFoundException("No group specified"); final Group group = dao.getEntityById(Group.class, groupId); - return group.getDTO(); + return group; } @Override - public GroupDTO getGroup(Long userId, String name) throws ObjectNotFoundException { + public Group getGroup(Long userId, String name) throws ObjectNotFoundException { if (userId == null) throw new ObjectNotFoundException("No user specified"); if (name == null) @@ -216,27 +209,20 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { List groups = user.getGroupsSpecified(); for (Group group: groups) if (group.getName().equals(name)) - return group.getDTO(); + return group; throw new ObjectNotFoundException("Group " + name + " not found"); } - /* - * (non-Javadoc) - * - * @see gr.ebs.gss.server.ejb.ExternalAPI#getGroups(java.lang.Long) - */ - public List getGroups(final Long userId) throws ObjectNotFoundException { + @Override + public List getGroups(final Long userId) throws ObjectNotFoundException { if (userId == null) throw new ObjectNotFoundException("No user specified"); final List groups = dao.getGroups(userId); - final List result = new ArrayList(); - for (final Group g : groups) - result.add(g.getDTO()); - return result; + return groups; } @Override - public List getFiles(Long userId, Long folderId, boolean ignoreDeleted) + public List getFiles(Long userId, Long folderId, boolean ignoreDeleted) throws ObjectNotFoundException, InsufficientPermissionsException { // Validate. if (userId == null) @@ -247,21 +233,12 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { Folder folder = dao.getEntityById(Folder.class, folderId); if (!folder.hasReadPermission(user)) throw new InsufficientPermissionsException("You don't have the permissions to read this folder"); - // Do the actual work. - List result = new ArrayList(); List files = dao.getFiles(folderId, userId, ignoreDeleted); - for (FileHeader f : files) - result.add(f.getDTO()); - return result; + return files; } - /* - * (non-Javadoc) - * - * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsers(java.lang.Long, - * java.lang.Long) - */ - public List getUsers(final Long userId, final Long groupId) throws ObjectNotFoundException { + @Override + public List getUsers(final Long userId, final Long groupId) throws ObjectNotFoundException { // Validate. if (userId == null) throw new ObjectNotFoundException("No user specified"); @@ -270,14 +247,11 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { // Do the actual work. final List users = dao.getUsers(groupId); - final List result = new ArrayList(); - for (final User u : users) - result.add(u.getDTO()); - return result; + return users; } @Override - public FolderDTO createFolder(Long userId, Long parentId, String name) + public Folder createFolder(Long userId, Long parentId, String name) throws DuplicateNameException, ObjectNotFoundException, InsufficientPermissionsException { // Validate. if (userId == null) @@ -315,7 +289,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { * @param creator * @return the new folder */ - private FolderDTO createFolder(String name, Folder parent, User creator) { + private Folder createFolder(String name, Folder parent, User creator) { Folder folder = new Folder(); folder.setName(name); if (parent != null) { @@ -351,17 +325,15 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { permission.setModifyACL(true); folder.addPermission(permission); } + + if(parent != null) + folder.setReadForAll(parent.isReadForAll()); + dao.create(folder); - return folder.getDTO(); + return folder; } - /* - * Deletes the given folder and all its subfolders and files - * Only the permissions for top folder are checked - * - * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteFolder(java.lang.Long, - * java.lang.Long) - */ + @Override public void deleteFolder(final Long userId, final Long folderId) throws InsufficientPermissionsException, ObjectNotFoundException { // Validate. if (userId == null) @@ -403,8 +375,9 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } } + @Override @SuppressWarnings("unchecked") - public List getSubfolders(Long userId, Long folderId) + public List getSubfolders(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException { if (userId == null) throw new ObjectNotFoundException("No user specified"); @@ -414,17 +387,18 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { Folder folder = dao.getEntityById(Folder.class, folderId); if (!folder.hasReadPermission(user)) throw new InsufficientPermissionsException("You don't have the permissions to read this folder"); - List result = new ArrayList(); + List result = new ArrayList(); if (folder.hasReadPermission(user)) for (Folder f : folder.getSubfolders()) if (f.hasReadPermission(user) && !f.isDeleted()) - result.add(f.getDTO()); + result.add(f); return result; } @Override - public FolderDTO updateFolder(Long userId, Long folderId, String folderName, - Set permissions) + public Folder updateFolder(Long userId, Long folderId, String folderName, + Boolean readForAll, + Set permissions) throws InsufficientPermissionsException, ObjectNotFoundException, DuplicateNameException { @@ -440,6 +414,9 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { throw new InsufficientPermissionsException("You don't have the necessary permissions"); if(permissions != null && !permissions.isEmpty() && !folder.hasModifyACLPermission(user)) throw new InsufficientPermissionsException("You don't have the necessary permissions"); + // Check permissions for making file public. + if (readForAll != null && !user.equals(folder.getOwner())) + throw new InsufficientPermissionsException("Only the owner can make a folder public or not public"); Folder parent = folder.getParent(); if (folderName != null) { @@ -452,20 +429,28 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } if (permissions != null) setFolderPermissions(user, folder, permissions); - + if (readForAll != null) + setFolderReadForAll(user, folder, readForAll); folder.getAuditInfo().setModificationDate(new Date()); folder.getAuditInfo().setModifiedBy(user); dao.update(folder); touchParentFolders(folder, user, new Date()); - return folder.getDTO(); + // Re-index the folder contents if it was modified. + if ((permissions != null && !permissions.isEmpty()) || readForAll != null) { + indexFolder(folder); + } + + return folder; } - /* - * (non-Javadoc) - * - * @see gr.ebs.gss.server.ejb.ExternalAPI#createGroup(java.lang.Long, - * java.lang.String) - */ + private void indexFolder(Folder folder) { + for (FileHeader fh : folder.getFiles()) + indexFile(fh.getId(), false); + for (Folder f : folder.getSubfolders()) + indexFolder(f); + } + + @Override public void createGroup(final Long userId, final String name) throws ObjectNotFoundException, DuplicateNameException { // Validate. if (userId == null) @@ -485,12 +470,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { owner.createGroup(name); } - /* - * (non-Javadoc) - * - * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteGroup(java.lang.Long, - * java.lang.Long) - */ + @Override public void deleteGroup(final Long userId, final Long groupId) throws ObjectNotFoundException, InsufficientPermissionsException { // Validate. if (userId == null) @@ -501,17 +481,20 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { // Do the actual work. final User owner = dao.getEntityById(User.class, userId); final Group group = dao.getEntityById(Group.class, groupId); + final Date now = new Date(); // Only delete the group if actually owned by the user. if (group.getOwner().equals(owner)) { List folders = dao.getFoldersPermittedForGroup(userId, groupId); for (Folder f : folders){ f.getPermissions().removeAll(group.getPermissions()); - for(FileHeader file : f.getFiles()) + for(FileHeader file : f.getFiles()){ file.getPermissions().removeAll(group.getPermissions()); + } } - List files = dao.getSharedFilesNotInSharedFolders(userId); - for(FileHeader h : files) + List files = dao.getFilesPermittedForGroup(userId, groupId); + for(FileHeader h : files){ h.getPermissions().removeAll(group.getPermissions()); + } owner.removeSpecifiedGroup(group); dao.delete(group); } @@ -519,7 +502,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } @Override - public FileHeaderDTO createFile(Long userId, Long folderId, String name, String mimeType, InputStream stream) + public FileHeader createFile(Long userId, Long folderId, String name, String mimeType, InputStream stream) throws DuplicateNameException, ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException { File file = null; @@ -535,6 +518,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { /* (non-Javadoc) * @see gr.ebs.gss.server.ejb.ExternalAPIRemote#indexFile(java.lang.Long, boolean) */ + @Override public void indexFile(Long fileId, boolean delete) { Connection qConn = null; Session session = null; @@ -600,12 +584,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { return secondFolder + File.separator + filename; } - /* - * (non-Javadoc) - * - * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteFile(java.lang.Long, - * java.lang.Long) - */ + @Override public void deleteFile(final Long userId, final Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException { // Validate. if (userId == null) @@ -628,14 +607,16 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { indexFile(fileId, true); } - private void deleteActualFile(String filePath) { - if (filePath == null) + @Override + public void deleteActualFile(String path) { + if (path == null) return; - File file = new File(filePath); + File file = new File(path); if (!file.delete()) - logger.error("Could not delete file " + filePath); + logger.error("Could not delete file " + path); } + @Override public void createTag(final Long userId, final Long fileHeaderId, final String tag) throws ObjectNotFoundException { if (userId == null) throw new ObjectNotFoundException("No user specified"); @@ -653,13 +634,15 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { touchParentFolders(parent, user, new Date()); } + @Override public Set getUserTags(final Long userId) throws ObjectNotFoundException { return dao.getUserTags(userId); } + @Override public void updateFile(Long userId, Long fileId, String name, String tagSet, Date modificationDate, Boolean versioned, - Boolean readForAll, Set permissions) + Boolean readForAll, Set permissions) throws DuplicateNameException, ObjectNotFoundException, InsufficientPermissionsException { if (userId == null) throw new ObjectNotFoundException("No user specified"); @@ -737,7 +720,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { touchParentFolders(parent, user, new Date()); // Re-index the file if it was modified. - if (name != null || tagSet != null) + if (name != null || tagSet != null || (permissions != null && !permissions.isEmpty()) || readForAll != null) indexFile(fileId, false); } @@ -768,6 +751,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { /* (non-Javadoc) * @see gr.ebs.gss.server.ejb.ExternalAPI#getFileContents(java.lang.Long, java.lang.Long, java.lang.Long) */ + @Override public InputStream getFileContents(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException { if (userId == null) throw new ObjectNotFoundException("No user specified"); @@ -793,10 +777,8 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } } - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#getFile(java.lang.Long, java.lang.Long) - */ - public FileHeaderDTO getFile(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException { + @Override + public FileHeader getFile(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException { if (userId == null) throw new ObjectNotFoundException("No user specified"); if (fileId == null) @@ -805,11 +787,11 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { final FileHeader file = dao.getEntityById(FileHeader.class, fileId); if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user)) throw new InsufficientPermissionsException("You don't have the necessary permissions"); - return file.getDTO(); + return file; } @Override - public FileBodyDTO getFileBody(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException { + public FileBody getFileBody(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException { if (userId == null) throw new ObjectNotFoundException("No user specified"); if (fileId == null) @@ -819,7 +801,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user)) throw new InsufficientPermissionsException("You don't have the necessary permissions"); FileBody body = dao.getEntityById(FileBody.class, bodyId); - return body.getDTO(); + return body; } @Override @@ -839,10 +821,12 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { return getRootFolder(owner.getId()); // Store the last element, since it requires special handling. String lastElement = pathElements.remove(pathElements.size() - 1); - FolderDTO cursor = getRootFolder(owner.getId()); + + Folder cursor = null; + Long rootFolderId = getRootFolderId(owner.getId()); // Traverse and verify the specified folder path. for (String pathElement : pathElements) { - cursor = getFolder(cursor.getId(), pathElement); + cursor = getFolder(cursor==null ? rootFolderId : cursor.getId(), pathElement); if (cursor.isDeleted()) throw new ObjectNotFoundException("Folder " + cursor.getPath() + " not found"); } @@ -850,14 +834,14 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { // Use the lastElement to retrieve the actual resource. Object resource = null; try { - FileHeaderDTO file = getFile(cursor.getId(), lastElement); + FileHeader file = getFile(cursor==null ? rootFolderId : cursor.getId(), lastElement); if (ignoreDeleted && file.isDeleted()) throw new ObjectNotFoundException("Resource not found"); resource = file; } catch (ObjectNotFoundException e) { // Perhaps the requested resource is not a file, so // check for folders as well. - FolderDTO folder = getFolder(cursor.getId(), lastElement); + Folder folder = getFolder(cursor==null ? rootFolderId : cursor.getId(), lastElement); if (ignoreDeleted && folder.isDeleted()) throw new ObjectNotFoundException("Resource not found"); resource = folder; @@ -869,7 +853,6 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { * Retrieve a file for the specified user that has the specified name and * its parent folder has id equal to folderId. * - * @param userId the ID of the current user * @param folderId the ID of the parent folder * @param name the name of the requested file * @return the file found @@ -877,14 +860,14 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { * found, with the exception message mentioning the precise * problem */ - private FileHeaderDTO getFile(Long folderId, String name) throws ObjectNotFoundException { + private FileHeader getFile(Long folderId, String name) throws ObjectNotFoundException { if (folderId == null) throw new ObjectNotFoundException("No parent folder specified"); if (StringUtils.isEmpty(name)) throw new ObjectNotFoundException("No file specified"); FileHeader file = dao.getFile(folderId, name); - return file.getDTO(); + return file; } /** @@ -898,17 +881,17 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { * found, with the exception message mentioning the precise * problem */ - private FolderDTO getFolder(Long parentId, String name) throws ObjectNotFoundException { + private Folder getFolder(Long parentId, String name) throws ObjectNotFoundException { if (parentId == null) throw new ObjectNotFoundException("No parent folder specified"); if (StringUtils.isEmpty(name)) throw new ObjectNotFoundException("No folder specified"); Folder folder = dao.getFolder(parentId, name); - return folder.getDTO(); + return folder; } - private FileHeaderDTO updateFileContents(Long userId, Long fileId, String mimeType, InputStream resourceInputStream) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException { + private FileHeader updateFileContents(Long userId, Long fileId, String mimeType, InputStream resourceInputStream) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException { File file = null; try { file = uploadFile(resourceInputStream, userId); @@ -929,9 +912,9 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { throw new ObjectNotFoundException("No destination specified"); Object destination = getResourceAtPath(userId, getParentPath(dest), true); - if (!(destination instanceof FolderDTO)) + if (!(destination instanceof Folder)) throw new ObjectNotFoundException("Destination parent folder not found"); - FolderDTO parent = (FolderDTO) destination; + Folder parent = (Folder) destination; copyFile(userId, fileId, parent.getId(), getLastElement(dest)); } @@ -947,9 +930,9 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { throw new ObjectNotFoundException("No destination specified"); Object destination = getResourceAtPath(ownerId, getParentPath(dest), true); - if (!(destination instanceof FolderDTO)) + if (!(destination instanceof Folder)) throw new ObjectNotFoundException("Destination parent folder not found"); - FolderDTO parent = (FolderDTO) destination; + Folder parent = (Folder) destination; copyFile(userId, fileId, parent.getId(), getLastElement(dest)); } @@ -1006,9 +989,9 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { throw new ObjectNotFoundException("No destination specified"); Object destination = getResourceAtPath(userId, getParentPath(dest), true); - if (!(destination instanceof FolderDTO)) + if (!(destination instanceof Folder)) throw new ObjectNotFoundException("Destination folder not found"); - FolderDTO parent = (FolderDTO) destination; + Folder parent = (Folder) destination; copyFolder(userId, folderId, parent.getId(), getLastElement(dest)); } @@ -1042,9 +1025,9 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { throw new ObjectNotFoundException("No destination specified"); Object destination = getResourceAtPath(ownerId, getParentPath(dest), true); - if (!(destination instanceof FolderDTO)) + if (!(destination instanceof Folder)) throw new ObjectNotFoundException("Destination folder not found"); - FolderDTO parent = (FolderDTO) destination; + Folder parent = (Folder) destination; copyFolderStructure(userId, folderId, parent.getId(), getLastElement(dest)); } @@ -1145,14 +1128,17 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { if (parent == null) throw new ObjectNotFoundException("The specified file has no parent folder"); User user = dao.getEntityById(User.class, userId); - if (!file.hasDeletePermission(user)) - throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")"); - - file.setDeleted(true); - dao.update(file); - touchParentFolders(parent, user, new Date()); + trashFile(user, file); + touchParentFolders(parent, user, new Date()); } + private void trashFile(User user, FileHeader file) throws InsufficientPermissionsException { + if (!file.hasDeletePermission(user)) + throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")"); + + file.setDeleted(true); + } + @Override public void moveFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, InsufficientPermissionsException, QuotaExceededException { if (userId == null) @@ -1165,9 +1151,9 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { throw new ObjectNotFoundException("No destination specified"); Object destination = getResourceAtPath(ownerId, getParentPath(dest), true); - if (!(destination instanceof FolderDTO)) + if (!(destination instanceof Folder)) throw new ObjectNotFoundException("Destination parent folder not found"); - FolderDTO parent = (FolderDTO) destination; + Folder parent = (Folder) destination; moveFile(userId, fileId, parent.getId(), getLastElement(dest)); } @@ -1222,7 +1208,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } @Override - public void moveFolderToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException { + public void moveFolderToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, InsufficientPermissionsException, QuotaExceededException { if (userId == null) throw new ObjectNotFoundException("No user specified"); if (ownerId == null) @@ -1233,34 +1219,77 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { throw new ObjectNotFoundException("No destination specified"); Object destination = getResourceAtPath(ownerId, getParentPath(dest), true); - if (!(destination instanceof FolderDTO)) + if (!(destination instanceof Folder)) throw new ObjectNotFoundException("Destination parent folder not found"); - FolderDTO parent = (FolderDTO) destination; + Folder parent = (Folder) destination; moveFolder(userId, folderId, parent.getId(), getLastElement(dest)); } @Override - public void moveFolder(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException { - // TODO Simple Move and delete of original folder, in production - // scenario we must first check individual files and folders permissions - copyFolderStructure(userId, folderId, destId, destName); - deleteFolder(userId, folderId); + public void moveFolder(Long userId, Long folderId, Long destId, String destName) + throws ObjectNotFoundException, InsufficientPermissionsException, + QuotaExceededException { + Folder source = dao.getEntityById(Folder.class, folderId); + Folder destination = dao.getEntityById(Folder.class, destId); + User user = dao.getEntityById(User.class, userId); + User sourceOwner = source.getOwner(); + User destinationOwner = destination.getOwner(); + // Do not move trashed folders and contents. + if (source.isDeleted()) + return; + // Check permissions. + if (!destination.hasWritePermission(user) + || !source.hasReadPermission(user) + || !source.hasWritePermission(user)) + throw new InsufficientPermissionsException("You don't have the " + + "necessary permissions"); + // Use the same timestamp for all subsequent modifications to make + // changes appear simultaneous. + Date now = new Date(); + // If source and destination are not in the same user's namespace, + // change owners and check quota. + if (!sourceOwner.equals(destinationOwner)) { + changeOwner(source, destinationOwner, user, now); + if (getQuotaLeft(destinationOwner.getId()) < 0) + throw new QuotaExceededException("Not enough free space " + + "available in destination folder"); + } + // Perform the move. + Folder oldParent = source.getParent(); + oldParent.removeSubfolder(source); + destination.addSubfolder(source); + // Mark the former parent and destination trees upwards as modified. + touchParentFolders(oldParent, user, now); + touchParentFolders(source, user, now); } - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#getDeletedFiles(java.lang.Long) + /** + * Recursively change the owner of the specified folder and all of its + * contents to the specified owner. Also mark them all as modified with the + * specified modifier and modificationDate. */ - public List getDeletedFiles(Long userId) throws ObjectNotFoundException { + private void changeOwner(Folder folder, User owner, User modifier, Date modificationDate) { + for (FileHeader file: folder.getFiles()) { + file.setOwner(owner); + file.getAuditInfo().setModificationDate(modificationDate); + file.getAuditInfo().setModifiedBy(modifier); + } + for (Folder sub: folder.getSubfolders()) + changeOwner(sub, owner, modifier, modificationDate); + folder.setOwner(owner); + folder.getAuditInfo().setModificationDate(modificationDate); + folder.getAuditInfo().setModifiedBy(modifier); + } + + @Override + public List getDeletedFiles(Long userId) throws ObjectNotFoundException { // Validate. if (userId == null) throw new ObjectNotFoundException("No user specified"); // Do the actual work. - final List result = new ArrayList(); final List files = dao.getDeletedFiles(userId); - for (final FileHeader f : files) - result.add(f.getDTO()); - return result; + return files; } @Override @@ -1277,34 +1306,39 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { if (parent == null) throw new ObjectNotFoundException("The specified file has no parent folder"); User user = dao.getEntityById(User.class, userId); - if (!file.hasDeletePermission(user)) - throw new InsufficientPermissionsException("User " + user.getUsername() + - " cannot restore file " + file.getName()); - - file.setDeleted(false); - dao.update(file); + untrashFile(user, file); touchParentFolders(parent, user, new Date()); } + private void untrashFile(User user, FileHeader file) throws InsufficientPermissionsException { + if (!file.hasDeletePermission(user)) + throw new InsufficientPermissionsException("User " + user.getUsername() + + " cannot restore file " + file.getName()); + + file.setDeleted(false); + } + @Override public void moveFolderToTrash(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException { - if (userId == null) - throw new ObjectNotFoundException("No user specified"); - if (folderId == null) - throw new ObjectNotFoundException("No folder specified"); - Folder folder = dao.getEntityById(Folder.class, folderId); - User user = dao.getEntityById(User.class, userId); - if (!folder.hasDeletePermission(user)) - throw new InsufficientPermissionsException("You don't have the necessary permissions"); - folder.setDeleted(true); - dao.update(folder); - touchParentFolders(folder, user, new Date()); - for (FileHeader file : folder.getFiles()) - moveFileToTrash(userId, file.getId()); - for (Folder subFolder : folder.getSubfolders()) - moveFolderToTrash(userId, subFolder.getId()); - - } + if (userId == null) + throw new ObjectNotFoundException("No user specified"); + if (folderId == null) + throw new ObjectNotFoundException("No folder specified"); + Folder folder = dao.getEntityById(Folder.class, folderId); + User user = dao.getEntityById(User.class, userId); + trashFolder(user, folder); + touchParentFolders(folder, user, new Date()); + } + + private void trashFolder(User user, Folder folder) throws ObjectNotFoundException, InsufficientPermissionsException { + if (!folder.hasDeletePermission(user)) + throw new InsufficientPermissionsException("You don't have the necessary permissions"); + folder.setDeleted(true); + for (FileHeader file : folder.getFiles()) + trashFile(user, file); + for (Folder subFolder : folder.getSubfolders()) + trashFolder(user, subFolder); + } @Override public void removeFolderFromTrash(Long userId, Long folderId) @@ -1315,50 +1349,50 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { throw new ObjectNotFoundException("No folder specified"); Folder folder = dao.getEntityById(Folder.class, folderId); User user = dao.getEntityById(User.class, userId); - if (!folder.hasDeletePermission(user)) - throw new InsufficientPermissionsException("User " + user.getUsername() + - " cannot restore folder " + folder.getName()); - folder.setDeleted(false); - for (FileHeader file : folder.getFiles()) - removeFileFromTrash(userId, file.getId()); - for (Folder subFolder : folder.getSubfolders()) - removeFolderFromTrash(userId, subFolder.getId()); - dao.update(folder); + untrashFolder(user, folder); touchParentFolders(folder, user, new Date()); } + private void untrashFolder(User user, Folder folder) throws ObjectNotFoundException, InsufficientPermissionsException { + if (!folder.hasDeletePermission(user)) + throw new InsufficientPermissionsException("User " + user.getUsername() + + " cannot restore folder " + folder.getName()); + folder.setDeleted(false); + for (FileHeader file : folder.getFiles()) + untrashFile(user, file); + for (Folder subFolder : folder.getSubfolders()) + untrashFolder(user, subFolder); + } + @Override - public List getDeletedRootFolders(Long userId) throws ObjectNotFoundException { + public List getDeletedRootFolders(Long userId) throws ObjectNotFoundException { List folders = dao.getDeletedRootFolders(userId); - List result = new ArrayList(); - for (Folder folder : folders) - result.add(folder.getDTO()); - return result; + return folders; } @Override public void emptyTrash(Long userId) throws ObjectNotFoundException, InsufficientPermissionsException { - List deletedRootFolders = getDeletedRootFolders(userId); - for (FolderDTO fdto : deletedRootFolders) - deleteFolder(userId, fdto.getId()); - List deletedFiles = getDeletedFiles(userId); - for (FileHeaderDTO filedto : deletedFiles) - deleteFile(userId, filedto.getId()); + List deletedRootFolders = getDeletedRootFolders(userId); + for (Folder folder : deletedRootFolders) + deleteFolder(userId, folder.getId()); + List deletedFiles = getDeletedFiles(userId); + for (FileHeader file : deletedFiles) + deleteFile(userId, file.getId()); } @Override public void restoreTrash(Long userId) throws ObjectNotFoundException, InsufficientPermissionsException { - List deletedRootFolders = getDeletedRootFolders(userId); - for (FolderDTO fdto : deletedRootFolders) - removeFolderFromTrash(userId, fdto.getId()); - List deletedFiles = getDeletedFiles(userId); - for (FileHeaderDTO filedto : deletedFiles) - removeFileFromTrash(userId, filedto.getId()); + List deletedRootFolders = getDeletedRootFolders(userId); + for (Folder folder : deletedRootFolders) + removeFolderFromTrash(userId, folder.getId()); + List deletedFiles = getDeletedFiles(userId); + for (FileHeader file : deletedFiles) + removeFileFromTrash(userId, file.getId()); } @Override public User createUser(String username, String name, String mail, - String peristentId) throws ObjectNotFoundException { + String idp, String idpid) throws ObjectNotFoundException { if (username == null) throw new ObjectNotFoundException("No username specified"); if (name == null) @@ -1368,14 +1402,17 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { user.setUsername(username); user.setName(name); user.setEmail(mail); - user.setPersistentId(peristentId); + user.setIdentityProvider(idp); + user.setIdentityProviderId(idpid); Date now = new Date(); AuditInfo auditInfo = new AuditInfo(); auditInfo.setCreationDate(now); auditInfo.setModificationDate(now); user.setAuditInfo(auditInfo); + user.setActive(true); user.generateAuthToken(); user.generateWebDAVPassword(); + user.setUserClass(getDefaultUserClass()); dao.create(user); // Make sure we get an ID in the user object. dao.flush(); @@ -1384,6 +1421,29 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { return user; } + /** + * Get the default user class, which is the one with the lowest quota. + */ + private UserClass getDefaultUserClass() { + return getUserClasses().get(0); + } + + @Override + public List getUserClasses() { + List classes = dao.getUserClasses(); + // Create a default user class for first-time use. Afterwards, the + // admin should modify or add to the userclass table. + if (classes.size() == 0) { + UserClass defaultClass = new UserClass(); + defaultClass.setName("default"); + Long defaultQuota = getConfiguration().getLong("quota", new Long(52428800L)); + defaultClass.setQuota(defaultQuota); + dao.create(defaultClass); + classes.add(defaultClass); + } + return classes; + } + @Override public User findUserByEmail(String email) { return dao.findUserByEmail(email); @@ -1410,11 +1470,8 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { return user; } - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#getFolderPermissions(java.lang.Long, java.lang.Long) - */ @Override - public Set getFolderPermissions(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException { + public Set getFolderPermissions(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException { if (userId == null) throw new ObjectNotFoundException("No user specified"); if (folderId == null) @@ -1424,14 +1481,14 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { if(!folder.hasReadPermission(user)) throw new InsufficientPermissionsException("You don't have the necessary permissions"); Set perms = folder.getPermissions(); - Set result = new LinkedHashSet(); + Set result = new LinkedHashSet(); for (Permission perm : perms) if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId())) - result.add(perm.getDTO()); + result.add(perm); for (Permission perm : perms) if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId())) { } else - result.add(perm.getDTO()); + result.add(perm); return result; } @@ -1446,41 +1503,50 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { * @throws ObjectNotFoundException * @throws InsufficientPermissionsException */ - private void setFolderPermissions(User user, Folder folder, Set permissions) throws ObjectNotFoundException, InsufficientPermissionsException { - // Delete previous entries - for (Permission perm: folder.getPermissions()) - dao.delete(perm); - folder.getPermissions().clear(); - for (PermissionDTO dto : permissions) { - if (dto.getUser()!=null && dto.getUser().getId().equals(folder.getOwner().getId()) && (!dto.hasRead() || !dto.hasWrite() || !dto.hasModifyACL())) - throw new InsufficientPermissionsException("Can't remove permissions from owner"); - // Don't include 'empty' permission - if (!dto.getRead() && !dto.getWrite() && !dto.getModifyACL()) continue; - folder.addPermission(getPermission(dto)); - } - dao.update(folder); - for (FileHeader file : folder.getFiles()) { - setFilePermissions(file, permissions); - Date now = new Date(); - file.getAuditInfo().setModificationDate(now); - file.getAuditInfo().setModifiedBy(user); + private void setFolderPermissions(User user, Folder folder, Set permissions) throws ObjectNotFoundException, InsufficientPermissionsException { + if (permissions != null && !permissions.isEmpty()) { + User owner = folder.getOwner(); + Permission ownerPerm = null; + for (Permission perm : permissions) + if (perm.getUser() != null && perm.getUser().getId().equals(owner.getId())) { + ownerPerm = perm; + break; + } + if (ownerPerm == null || !ownerPerm.hasRead() || !ownerPerm.hasWrite() || !ownerPerm.hasModifyACL()) + throw new InsufficientPermissionsException("Can't remove permissions from owner"); + // Delete previous entries + for (Permission perm: folder.getPermissions()) + dao.delete(perm); + folder.getPermissions().clear(); + for (Permission p : permissions) { + // Skip 'empty' permission entries. + if (!p.getRead() && !p.getWrite() && !p.getModifyACL()) continue; + folder.addPermission(getPermission(p)); + } + dao.update(folder); + for (FileHeader file : folder.getFiles()) { + setFilePermissions(file, permissions); + Date now = new Date(); + file.getAuditInfo().setModificationDate(now); + file.getAuditInfo().setModifiedBy(user); + } + for (Folder sub : folder.getSubfolders()) + setFolderPermissions(user, sub, permissions); } - for (Folder sub : folder.getSubfolders()) - setFolderPermissions(user, sub, permissions); } - private Permission getPermission(PermissionDTO dto) throws ObjectNotFoundException { + private Permission getPermission(Permission perm) throws ObjectNotFoundException { Permission res = new Permission(); - if (dto.getGroup() != null) - res.setGroup(dao.getEntityById(Group.class, dto.getGroup().getId())); - else if (dto.getUser() != null) - if (dto.getUser().getId() == null) - res.setUser(dao.getUser(dto.getUser().getUsername())); + if (perm.getGroup() != null) + res.setGroup(dao.getEntityById(Group.class, perm.getGroup().getId())); + else if (perm.getUser() != null) + if (perm.getUser().getId() == null) + res.setUser(dao.getUser(perm.getUser().getUsername())); else - res.setUser(dao.getEntityById(User.class, dto.getUser().getId())); - res.setRead(dto.hasRead()); - res.setWrite(dto.hasWrite()); - res.setModifyACL(dto.hasModifyACL()); + res.setUser(dao.getEntityById(User.class, perm.getUser().getId())); + res.setRead(perm.hasRead()); + res.setWrite(perm.hasWrite()); + res.setModifyACL(perm.hasModifyACL()); return res; } @@ -1488,18 +1554,12 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsersByUserNameLike(java.lang.String) */ @Override - public List getUsersByUserNameLike(String username) { + public List getUsersByUserNameLike(String username) { List users = dao.getUsersByUserNameLike(username); - List result = new ArrayList(); - for (User u : users) - result.add(u.getDTO()); - return result; + return users; } - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#addUserToGroup(java.lang.Long, java.lang.Long, java.lang.Long) - */ @Override public void addUserToGroup(Long userId, Long groupId, Long userToAddId) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException { if (userId == null) @@ -1530,22 +1590,19 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } @Override - public List getSharedRootFolders(Long userId) throws ObjectNotFoundException { + public List getSharedRootFolders(Long userId) throws ObjectNotFoundException { if (userId == null) throw new ObjectNotFoundException("No user specified"); List folders = dao.getSharedRootFolders(userId); - List result = new ArrayList(); + List result = new ArrayList(); for (Folder f : folders) { - FolderDTO dto = f.getDTO(); - dto.setSubfolders(getSharedSubfolders(userId, f.getId())); - result.add(dto); + Folder lf = f; + lf.setSubfolders(getSharedSubfolders(userId, f.getId())); + result.add(lf); } return result; } - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#removeMemberFromGroup(java.lang.Long, java.lang.Long, java.lang.Long) - */ @Override public void removeMemberFromGroup(Long userId, Long groupId, Long memberId) throws ObjectNotFoundException, InsufficientPermissionsException { if (userId == null) @@ -1565,20 +1622,20 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } @Override - public List getUsersSharingFoldersForUser(Long userId) throws ObjectNotFoundException { + public List getUsersSharingFoldersForUser(Long userId) throws ObjectNotFoundException { List users = dao.getUsersSharingFoldersForUser(userId); List usersFiles = dao.getUsersSharingFilesForUser(userId); - List res = new ArrayList(); + List result = new ArrayList(); for (User u : users) - res.add(u.getDTO()); + result.add(u); for(User fu : usersFiles) if(!users.contains(fu)) - res.add(fu.getDTO()); - return res; + result.add(fu); + return result; } @Override - public Set getFilePermissions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException { + public Set getFilePermissions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException { if (userId == null) throw new ObjectNotFoundException("No user specified"); if (fileId == null) @@ -1588,14 +1645,14 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { if(!folder.hasReadPermission(user)) throw new InsufficientPermissionsException("You don't have the necessary permissions"); Set perms = folder.getPermissions(); - Set result = new LinkedHashSet(); + Set result = new LinkedHashSet(); for (Permission perm : perms) if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId())) - result.add(perm.getDTO()); + result.add(perm); for (Permission perm : perms) if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId())) { } else - result.add(perm.getDTO()); + result.add(perm); return result; } @@ -1610,108 +1667,99 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { * @throws InsufficientPermissionsException */ private void setFilePermissions(FileHeader file, - Set permissions) + Set permissions) throws ObjectNotFoundException, InsufficientPermissionsException { if (permissions != null && !permissions.isEmpty()) { + Permission ownerPerm = null; + for (Permission perm : permissions) + if (perm.getUser() != null && perm.getUser().getId().equals(file.getOwner().getId())) { + ownerPerm = perm; + break; + } + if (ownerPerm == null || !ownerPerm.hasRead() || !ownerPerm.hasWrite() || !ownerPerm.hasModifyACL()) + throw new InsufficientPermissionsException("Can't remove permissions from owner"); // Delete previous entries. for (Permission perm: file.getPermissions()) dao.delete(perm); file.getPermissions().clear(); - for (PermissionDTO dto : permissions) { - if (dto.getUser()!=null && dto.getUser().getId().equals(file.getOwner().getId()) && (!dto.hasRead() || !dto.hasWrite() || !dto.hasModifyACL())) - throw new InsufficientPermissionsException("Can't remove permissions from owner"); - // Don't include 'empty' permission. - if (!dto.getRead() && !dto.getWrite() && !dto.getModifyACL()) continue; - file.addPermission(getPermission(dto)); + for (Permission perm : permissions) { + // Skip 'empty' permission entries. + if (!perm.getRead() && !perm.getWrite() && !perm.getModifyACL()) continue; + file.addPermission(getPermission(perm)); } dao.flush(); } } @Override - public List getSharedFilesNotInSharedFolders(Long userId) throws ObjectNotFoundException { + public List getSharedFilesNotInSharedFolders(Long userId) throws ObjectNotFoundException { if (userId == null) throw new ObjectNotFoundException("No user specified"); List files = dao.getSharedFilesNotInSharedFolders(userId); - List result = new ArrayList(); - for (FileHeader f : files) - result.add(f.getDTO()); - return result; + return files; } @Override - public List getSharedFiles(Long userId) throws ObjectNotFoundException { + public List getSharedFiles(Long userId) throws ObjectNotFoundException { if (userId == null) throw new ObjectNotFoundException("No user specified"); List files = dao.getSharedFiles(userId); - List result = new ArrayList(); - for (FileHeader f : files) - result.add(f.getDTO()); - return result; + return files; } @Override - public List getSharedFolders(Long userId) throws ObjectNotFoundException { + public List getSharedFolders(Long userId) throws ObjectNotFoundException { if (userId == null) throw new ObjectNotFoundException("No user specified"); List folders = dao.getSharedFolders(userId); - List result = new ArrayList(); - for (Folder f : folders) - result.add(f.getDTO()); - return result; + return folders; } - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#getSharedFiles(java.lang.Long, java.lang.Long) - */ @Override - public List getSharedFiles(Long ownerId, Long callingUserId) throws ObjectNotFoundException { + public List getSharedFiles(Long ownerId, Long callingUserId) throws ObjectNotFoundException { if (ownerId == null) throw new ObjectNotFoundException("No owner specified"); if (callingUserId == null) throw new ObjectNotFoundException("No calling user specified"); List folders = dao.getSharedFiles(ownerId, callingUserId); - List result = new ArrayList(); - for (FileHeader f : folders) - result.add(f.getDTO()); - return result; + return folders; } @Override - public List getSharedRootFolders(Long ownerId, Long callingUserId) throws ObjectNotFoundException { + public List getSharedRootFolders(Long ownerId, Long callingUserId) throws ObjectNotFoundException { if (ownerId == null) throw new ObjectNotFoundException("No owner specified"); if (callingUserId == null) throw new ObjectNotFoundException("No calling user specified"); List folders = dao.getSharedRootFolders(ownerId, callingUserId); - List result = new ArrayList(); + List result = new ArrayList(); for (Folder f : folders) { - FolderDTO dto = f.getDTO(); - dto.setSubfolders(getSharedSubfolders(ownerId, callingUserId, f.getId())); - result.add(dto); + Folder lf = f; + lf.setSubfolders(getSharedSubfolders(ownerId, callingUserId, f.getId())); + result.add(lf); } return result; } @Override - public List getSharedSubfolders(Long userId, Long folderId) throws ObjectNotFoundException { + public List getSharedSubfolders(Long userId, Long folderId) throws ObjectNotFoundException { if (userId == null) throw new ObjectNotFoundException("No user specified"); if (folderId == null) throw new ObjectNotFoundException("No folder specified"); User user = dao.getEntityById(User.class, userId); Folder folder = dao.getEntityById(Folder.class, folderId); - List result = new ArrayList(); - if (folder.isShared(user)) + List result = new ArrayList(); + if (folder.isShared(user) || folder.isReadForAll()) for (Folder f : folder.getSubfolders()) - if (f.isShared(user) && !f.isDeleted()) - result.add(f.getDTO()); + if ((f.isShared(user) || f.isReadForAll()) && !f.isDeleted()) + result.add(f); return result; } @Override - public List getSharedSubfolders(Long userId, Long callingUserId, Long folderId) throws ObjectNotFoundException { + public List getSharedSubfolders(Long userId, Long callingUserId, Long folderId) throws ObjectNotFoundException { if (userId == null) throw new ObjectNotFoundException("No user specified"); if (callingUserId == null) @@ -1720,127 +1768,96 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { throw new ObjectNotFoundException("No folder specified"); User user = dao.getEntityById(User.class, callingUserId); Folder folder = dao.getEntityById(Folder.class, folderId); - List result = new ArrayList(); + List result = new ArrayList(); if (folder.isSharedForOtherUser(user)) for (Folder f : folder.getSubfolders()) if (f.isSharedForOtherUser(user) && !f.isDeleted()){ - FolderDTO dto = f.getDTO(); - dto.setSubfolders(getSharedSubfolders(userId, callingUserId, dto.getId())); - result.add(dto); + Folder lf = f; + lf.setSubfolders(getSharedSubfolders(userId, callingUserId, lf.getId())); + result.add(lf); } return result; } - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#searchFiles(java.lang.Long, java.lang.String) - */ @Override - public List searchFiles(Long userId, String query) throws ObjectNotFoundException { + public List searchFiles(Long userId, String query) throws ObjectNotFoundException { + long startTime = System.currentTimeMillis(); if (userId == null) throw new ObjectNotFoundException("No user specified"); User user = getUser(userId); if (query == null) throw new ObjectNotFoundException("No query specified"); List files = search(user.getId(), query); - List res = new ArrayList(); - for(FileHeader f : files) - res.add(f.getDTO()); - return res; + + long stopTime = System.currentTimeMillis(); + logger.info("Total time: " + (stopTime - startTime)); + return files; } /** * Performs the actuals search on the solr server and returns the results * - * We have to use the dismax query type (instead of the - * standard) because it allows for search time field boosting. This is because we can't use indexing - * time field boosting due to the patched rich indexing API that does not allow it - * * @param userId * @param query * @return a List of FileHeader objects */ private List search(Long userId, String query) { + final int maxRows = 100; + List result = new ArrayList(); try { - HttpClient httpClient = new HttpClient(); - - GetMethod method = new GetMethod(getConfiguration().getString("solrSelectUrl")); - NameValuePair[] params = {new NameValuePair("qt", "dismax"), - new NameValuePair("q", query), - new NameValuePair("sort", "score desc"), - new NameValuePair("indent", "on")}; - method.setQueryString(params); - int retryCount = 0; - int statusCode = 0; - String response = null; - do { - statusCode = httpClient.executeMethod(method); - logger.debug("HTTP status: " + statusCode); - response = method.getResponseBodyAsString(); - logger.debug(response); - retryCount++; - if (statusCode != 200 && retryCount < 3) - try { - Thread.sleep(3000); //Give Solr a little time to be available - } catch (InterruptedException e) { - } - } while (statusCode != 200 && retryCount < 3); - if (statusCode != 200) - throw new EJBException("Search query return error:\n" + response); - - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - DocumentBuilder db = dbf.newDocumentBuilder(); - Document doc = db.parse(method.getResponseBodyAsStream()); - method.releaseConnection(); - - Node root = doc.getElementsByTagName("response").item(0); - Node lst = root.getFirstChild().getNextSibling(); - Node status = lst.getFirstChild().getNextSibling(); - if (status.getAttributes().getNamedItem("name").getNodeValue().equals("status") && - status.getTextContent().equals("0")) { - List fileResult = new ArrayList(); - Node result = lst.getNextSibling().getNextSibling(); - NodeList docs = result.getChildNodes(); - User user = getUser(userId); - for (int i=1; i groups = dao.getGroupsContainingUser(userId); + String constructedQuery = escapeCharacters(normalizeSearchQuery(query)) + " AND (public: true OR ureaders: " + userId; + if (!groups.isEmpty()) { + constructedQuery += " OR ("; + for (int i=0; i maxRows) { + solrQuery.setRows(Integer.valueOf((int) results.getNumFound())); + response = solr.query(solrQuery); + results = response.getResults(); + } + long stopTime = System.currentTimeMillis(); + logger.info("Search time:" + (stopTime - startTime)); + User user = getUser(userId); + startTime = System.currentTimeMillis(); + for (SolrDocument d : results) { + Long id = Long.valueOf((String) d.getFieldValue("id")); + try { + FileHeader f = dao.getEntityById(FileHeader.class, id); + result.add(f); + } catch (ObjectNotFoundException e) { + logger.warn("Search result id " + id + " cannot be found", e); } - return fileResult; } - throw new EJBException(); - } catch (HttpException e) { + stopTime = System.currentTimeMillis(); + logger.info("File loads: " + (stopTime - startTime)); + } catch (MalformedURLException e) { + logger.error(e); throw new EJBException(e); - } catch (IOException e) { - throw new EJBException(e); - } catch (SAXException e) { - throw new EJBException(e); - } catch (ParserConfigurationException e) { + } catch (SolrServerException e) { + logger.error(e); throw new EJBException(e); } catch (ObjectNotFoundException e) { + logger.error(e); throw new EJBException(e); } + return result; } - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#copyFiles(java.lang.Long, java.util.List, java.lang.Long) - */ @Override public void copyFiles(Long userId, List fileIds, Long destId) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException { for(Long l : fileIds){ @@ -1851,9 +1868,6 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#moveFiles(java.lang.Long, java.util.List, java.lang.Long) - */ @Override public void moveFiles(Long userId, List fileIds, Long destId) throws InsufficientPermissionsException, ObjectNotFoundException, QuotaExceededException { for(Long l : fileIds){ @@ -1863,58 +1877,6 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteFiles(java.lang.Long, java.util.List) - */ - @Override - public void deleteFiles(Long userId, List fileIds) throws ObjectNotFoundException, InsufficientPermissionsException { - if (userId == null) - throw new ObjectNotFoundException("No user specified"); - final User user = dao.getEntityById(User.class, userId); - List filesToRemove = new ArrayList(); - //first delete database objects - for(Long fileId : fileIds){ - if (fileId == null) - throw new ObjectNotFoundException("No file specified"); - final FileHeader file = dao.getEntityById(FileHeader.class, fileId); - final Folder parent = file.getFolder(); - if (parent == null) - throw new ObjectNotFoundException("The specified file has no parent folder"); - if (!file.hasDeletePermission(user)) - throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")"); - - parent.removeFile(file); - for (final FileBody body : file.getBodies()) - filesToRemove.add(body.getStoredFilePath()); - dao.delete(file); - touchParentFolders(parent, user, new Date()); - } - //then remove physical files if everything is ok - for(String physicalFileName : filesToRemove) - deleteActualFile(physicalFileName); - //then unindex deleted files - for(Long fileId : fileIds) - indexFile(fileId, true); - - } - - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#moveFilesToTrash(java.lang.Long, java.util.List) - */ - @Override - public void moveFilesToTrash(Long userId, List fileIds) throws ObjectNotFoundException, InsufficientPermissionsException { - for(Long l : fileIds) - moveFileToTrash(userId, l); - - } - - @Override - public void removeFilesFromTrash(Long userId, List fileIds) throws ObjectNotFoundException, InsufficientPermissionsException { - for(Long l : fileIds) - removeFileFromTrash(userId, l); - - } - @Override public Nonce createNonce(Long userId) throws ObjectNotFoundException { if (userId == null) @@ -1951,9 +1913,6 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { user.setNonceExpiryDate(nonceExpiryDate); } - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#getUserStatistics(java.lang.Long) - */ @Override public StatsDTO getUserStatistics(Long userId) throws ObjectNotFoundException { if (userId == null) @@ -1968,57 +1927,6 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { return stats; } - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#getVersions(java.lang.Long, java.lang.Long) - */ - @Override - public List getVersions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException { - if (userId == null) - throw new ObjectNotFoundException("No user specified"); - if (fileId == null) - throw new ObjectNotFoundException("No file specified"); - User user = dao.getEntityById(User.class, userId); - FileHeader header = dao.getEntityById(FileHeader.class, fileId); - if(!header.hasReadPermission(user)) - throw new InsufficientPermissionsException("You don't have the necessary permissions"); - List result = new LinkedList(); - for(int i = header.getBodies().size()-1 ; i>=0; i--) - result.add(header.getBodies().get(i).getDTO()); - return result; - } - - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#removeVersion(java.lang.Long, java.lang.Long, java.lang.Long) - */ - @Override - public void removeVersion(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException { - if (userId == null) - throw new ObjectNotFoundException("No user specified"); - if (fileId == null) - throw new ObjectNotFoundException("No file specified"); - if (bodyId == null) - throw new ObjectNotFoundException("No body specified"); - User user = dao.getEntityById(User.class, userId); - FileHeader header = dao.getEntityById(FileHeader.class, fileId); - if(!header.hasWritePermission(user)) - throw new InsufficientPermissionsException("You don't have the necessary permissions"); - FileBody body = dao.getEntityById(FileBody.class, bodyId); - if(body.equals(header.getCurrentBody())){ - - if(header.getBodies().size() == 1) - throw new InsufficientPermissionsException("You cant delete this version, Delete file instead!"); - for(FileBody b : header.getBodies()) - if(b.getVersion() == body.getVersion()-1) - header.setCurrentBody(b); - } - deleteActualFile(body.getStoredFilePath()); - header.getBodies().remove(body); - - Folder parent = header.getFolder(); - touchParentFolders(parent, user, new Date()); - - } - @Override public void restoreVersion(Long userId, Long fileId, int version) throws ObjectNotFoundException, InsufficientPermissionsException, GSSIOException, QuotaExceededException { if (userId == null) @@ -2069,157 +1977,85 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } /** - * Gets the quota left for specified userId - * @param userId - * @return + * Gets the quota left for specified user ID. */ - private Long getQuotaLeft(Long userId){ + private Long getQuotaLeft(Long userId) throws ObjectNotFoundException{ Long fileSize = dao.getFileSize(userId); Long quota = getQuota(userId); return quota - fileSize; } /** - * Gets the quota for specified userId - * @param userId - * @return + * Gets the quota for specified user ID. */ - private Long getQuota(@SuppressWarnings("unused") Long userId){ - Long quota = getConfiguration().getLong("quota", new Long(52428800L)); - return quota; + private Long getQuota(Long userId) throws ObjectNotFoundException{ + UserClass uc = getUser(userId).getUserClass(); + if (uc == null) + uc = getDefaultUserClass(); + return uc.getQuota(); } - public void rebuildSolrIndex() { - MessageProducer sender = null; - Session session = null; - Connection qConn = null; + @Override + @TransactionAttribute(TransactionAttributeType.NEVER) + public String rebuildSolrIndex() { try { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - DocumentBuilder db = dbf.newDocumentBuilder(); - Document doc = db.newDocument(); - Node root = doc.createElement("delete"); - doc.appendChild(root); - Node queryNode = doc.createElement("query"); - root.appendChild(queryNode); - queryNode.appendChild(doc.createTextNode("*:*")); - - TransformerFactory fact = TransformerFactory.newInstance(); - Transformer trans = fact.newTransformer(); - trans.setOutputProperty(OutputKeys.INDENT, "yes"); - StringWriter sw = new StringWriter(); - StreamResult sr = new StreamResult(sw); - DOMSource source = new DOMSource(doc); - trans.transform(source, sr); - logger.debug(sw.toString()); - - HttpClient httpClient = new HttpClient(); - PostMethod method = new PostMethod(getConfiguration().getString("solrUpdateUrl")); - method.setRequestEntity(new StringRequestEntity(sw.toString())); - int retryCount = 0; - int statusCode = 0; - String response = null; - do { - statusCode = httpClient.executeMethod(method); - logger.debug("HTTP status: " + statusCode); - response = method.getResponseBodyAsString(); - logger.debug(response); - retryCount++; - if (statusCode != 200 && retryCount < 3) - try { - Thread.sleep(10000); //Give Solr a little time to be available - } catch (InterruptedException e) { - } - } while (statusCode != 200 && retryCount < 3); - method.releaseConnection(); - if (statusCode != 200) - throw new EJBException("Cannot clear Solr index. Solr response is:\n" + response); - List fileIds = dao.getAllFileIds(); - - Context jndiCtx = new InitialContext(); - ConnectionFactory factory = (QueueConnectionFactory) jndiCtx.lookup("java:/JmsXA"); - Queue queue = (Queue) jndiCtx.lookup("queue/gss-indexingQueue"); - qConn = factory.createConnection(); - session = qConn.createSession(false, Session.AUTO_ACKNOWLEDGE); - sender = session.createProducer(queue); + CommonsHttpSolrServer solr = new CommonsHttpSolrServer(getConfiguration().getString("solr.url")); + solr.deleteByQuery("*:*"); + solr.commit(); + logger.info("Deleted everything in solr"); + List fileIds = dao.getAllFileIds(); + logger.info("Total of " + fileIds.size() + " will be indexed"); + int i = 0; for (Long id : fileIds) { - MapMessage map = session.createMapMessage(); - map.setObject("id", id); - map.setBoolean("delete", false); - sender.send(map); + postFileToSolr(solr, id); + i++; + if (i % 10 == 0) { + solr.commit(); + logger.info("Sent commit to solr at file " + i); + } } - sendOptimize(httpClient, 0); - } catch (DOMException e) { - throw new EJBException(e); - } catch (TransformerConfigurationException e) { - throw new EJBException(e); - } catch (IllegalArgumentException e) { - throw new EJBException(e); - } catch (HttpException e) { - throw new EJBException(e); - } catch (UnsupportedEncodingException e) { - throw new EJBException(e); - } catch (ParserConfigurationException e) { - throw new EJBException(e); - } catch (TransformerException e) { - throw new EJBException(e); + solr.optimize(); + solr.commit(); + logger.info("Finished indexing of " + i + " files"); + return "Finished indexing of " + i + " files"; } catch (IOException e) { throw new EJBException(e); - } catch (NamingException e) { + } catch (SolrServerException e) { throw new EJBException(e); - } catch (JMSException e) { - throw new EJBException(e); - } - finally { - try { - if (sender != null) - sender.close(); - if (session != null) - session.close(); - if (qConn != null) - qConn.close(); - } - catch (JMSException e) { - logger.warn(e); - } } } - /** - * Sends a optimize message to the solr server - * - * @param httpClient - * @param retryCount If the commit fails, it is retried three times. This parameter is passed in the recursive - * calls to stop the recursion - * @throws UnsupportedEncodingException - * @throws IOException - * @throws HttpException - */ - private void sendOptimize(HttpClient httpClient, int retryCount) throws UnsupportedEncodingException, IOException, HttpException { - PostMethod method = null; + @Override + @TransactionAttribute(TransactionAttributeType.NEVER) + public String refreshSolrIndex() { try { - logger.debug("Optimize retry: " + retryCount); - method = new PostMethod(getConfiguration().getString("solrUpdateUrl")); - method.setRequestEntity(new StringRequestEntity("", "text/xml", "iso8859-1")); - int statusCode = httpClient.executeMethod(method); - logger.debug("HTTP status: " + statusCode); - String response = method.getResponseBodyAsString(); - logger.debug(response); - if (statusCode != 200 && retryCount < 2) { - try { - Thread.sleep(10000); //Give Solr a little time to be available - } catch (InterruptedException e) { - } - sendOptimize(httpClient, retryCount + 1); + CommonsHttpSolrServer solr = new CommonsHttpSolrServer(getConfiguration().getString("solr.url")); + + List fileIds = dao.getAllFileIds(); + logger.info("Total of " + fileIds.size() + " will be indexed"); + int i = 0; + for (Long id : fileIds) { + postFileToSolr(solr, id); + i++; } - } - finally { - if (method != null) - method.releaseConnection(); + if (i % 10 == 0) { + solr.commit(); + logger.info("Sent commit to solr at file " + i); + } + solr.optimize(); + solr.commit(); + logger.info("Finished indexing of " + i + " files"); + return "Finished indexing of " + i + " files"; + } catch (IOException e) { + throw new EJBException(e); + } catch (SolrServerException e) { + throw new EJBException(e); } } - public FileHeaderDTO createFile(Long userId, Long folderId, String name, String mimeType, long fileSize, String filePath) + @Override + public FileHeader createFile(Long userId, Long folderId, String name, String mimeType, long fileSize, String filePath) throws DuplicateNameException, ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException { // Validate. @@ -2252,6 +2088,8 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { parent.addFile(file); // set file owner to folder owner file.setOwner(parent.getOwner()); + //set file's readForAll value according to parent folder readForAll value + file.setReadForAll(parent.isReadForAll()); final Date now = new Date(); final AuditInfo auditInfo = new AuditInfo(); @@ -2283,13 +2121,11 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { dao.flush(); indexFile(file.getId(), false); - return file.getDTO(); + return file; } - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#updateFileContents(java.lang.Long, java.lang.Long, java.lang.String, java.io.InputStream) - */ - public FileHeaderDTO updateFileContents(Long userId, Long fileId, String mimeType, long fileSize, String filePath) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException { + @Override + public FileHeader updateFileContents(Long userId, Long fileId, String mimeType, long fileSize, String filePath) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException { if (userId == null) throw new ObjectNotFoundException("No user specified"); if (fileId == null) @@ -2322,7 +2158,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { touchParentFolders(parent, owner, new Date()); indexFile(fileId, false); - return file.getDTO(); + return file; } /** @@ -2367,13 +2203,13 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { * @param filePath the uploaded file full path * @param header the file header that will be associated with the new body * @param auditInfo the audit info - * @param owner the owner of the file * @throws FileNotFoundException * @throws QuotaExceededException + * @throws ObjectNotFoundException if the owner was not found */ private void createFileBody(String name, String mimeType, long fileSize, String filePath, FileHeader header, AuditInfo auditInfo) - throws FileNotFoundException, QuotaExceededException { + throws FileNotFoundException, QuotaExceededException, ObjectNotFoundException { long currentTotalSize = 0; if (!header.isVersioned() && header.getCurrentBody() != null && header.getBodies() != null) @@ -2420,6 +2256,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } + @Override @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public File uploadFile(InputStream stream, Long userId) throws IOException, ObjectNotFoundException { if (userId == null) @@ -2453,6 +2290,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } + @Override public void createFileUploadProgress(Long userId, String filename, Long bytesTransfered, Long fileSize) throws ObjectNotFoundException{ if (userId == null) @@ -2475,6 +2313,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } + @Override public void removeFileUploadProgress(Long userId, String filename) throws ObjectNotFoundException{ if (userId == null) throw new ObjectNotFoundException("No user specified"); @@ -2489,45 +2328,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } @Override - public FolderDTO getFolderWithSubfolders(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException { - if (userId == null) - throw new ObjectNotFoundException("No user specified"); - if (folderId == null) - throw new ObjectNotFoundException("No folder specified"); - final User user = dao.getEntityById(User.class, userId); - final Folder folder = dao.getEntityById(Folder.class, folderId); - // Check permissions - if (!folder.hasReadPermission(user)) - throw new InsufficientPermissionsException("You don't have the permissions to read this folder"); - List subfolders = new ArrayList(); - if (folder.hasReadPermission(user)) - for (Folder f : folder.getSubfolders()) - if (f.hasReadPermission(user) && !f.isDeleted()) - subfolders.add(f.getDTO()); - FolderDTO result = folder.getDTO(); - result.setSubfolders(subfolders); - return folder.getDTO(); - } - - @Override - public FolderDTO getFolderWithSubfolders(Long userId, Long callingUserId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException { - if (userId == null) - throw new ObjectNotFoundException("No user specified"); - if (folderId == null) - throw new ObjectNotFoundException("No folder specified"); - User user = dao.getEntityById(User.class, callingUserId); - Folder folder = dao.getEntityById(Folder.class, folderId); - // Check permissions - if (!folder.hasReadPermission(user)) - throw new InsufficientPermissionsException("You don't have the permissions to read this folder"); - - FolderDTO result = folder.getDTO(); - result.setSubfolders(getSharedSubfolders(userId, callingUserId, folder.getId())); - return result; - } - - @Override - public FileBodyDTO getFileVersion(Long userId, Long fileId, int version) + public FileBody getFileVersion(Long userId, Long fileId, int version) throws ObjectNotFoundException, InsufficientPermissionsException { if (userId == null) throw new ObjectNotFoundException("No user specified"); @@ -2540,7 +2341,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user)) throw new InsufficientPermissionsException("You don't have the necessary permissions"); FileBody body = dao.getFileVersion(fileId, version); - return body.getDTO(); + return body; } @Override @@ -2571,13 +2372,6 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { return true; } - /** - * Reset WebDAV password for given user. - * - * @param userId - * @return the new password - * @throws ObjectNotFoundException - */ @Override public String resetWebDAVPassword(Long userId) throws ObjectNotFoundException { if (userId == null) @@ -2587,4 +2381,412 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { return user.getWebDAVPassword(); } + @Override + public Invitation findInvite(String code) { + if (code == null) + return null; + return dao.findInvite(code); + } + + @Override + public void createLdapUser(String username, String firstname, String lastname, String email, String password) { + LDAPConnection lc = new LDAPConnection(); + LDAPAttributeSet attributeSet = new LDAPAttributeSet(); + attributeSet.add(new LDAPAttribute("objectClass", getConfiguration().getStringArray("objectClass"))); + attributeSet.add(new LDAPAttribute("uid", username)); + attributeSet.add(new LDAPAttribute("cn", new String[]{firstname + " " + lastname})); + attributeSet.add(new LDAPAttribute("sn", lastname)); + attributeSet.add(new LDAPAttribute("givenName", firstname)); + attributeSet.add(new LDAPAttribute("mail", email)); + attributeSet.add(new LDAPAttribute("userPassword", password)); + String dn = "uid=" + username + "," + getConfiguration().getString("baseDn"); + LDAPEntry newEntry = new LDAPEntry(dn, attributeSet); + try { + lc.connect(getConfiguration().getString("ldapHost"), LDAPConnection.DEFAULT_PORT); + lc.bind(LDAPConnection.LDAP_V3, getConfiguration().getString("bindDn"), + getConfiguration().getString("bindPassword").getBytes("UTF8")); + lc.add(newEntry); + logger.info("Successfully added LDAP account: " + dn); + lc.disconnect(); + } catch(LDAPException e) { + throw new RuntimeException(e); + } catch(UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + + } + + @Override + public UserClass upgradeUserClass(String username, String code) throws ObjectNotFoundException, InvitationUsedException { + User user = findUser(username); + if (user == null) + throw new ObjectNotFoundException("The user was not found"); + Invitation invite = findInvite(code); + if (invite.getUser() != null) + throw new InvitationUsedException("This code has already been used"); + invite.setUser(user); + UserClass couponClass = getCouponUserClass(); + user.setUserClass(couponClass); + return couponClass; + } + + @Override + public UserClass getCouponUserClass() { + return dao.findCouponUserClass(); + } + + /** + * Set the provided readForAll as the new readforAll value of the specified + * folder and sub-folders. + * + * @param user + * @param folder + * @param readForAll + * @throws ObjectNotFoundException + * + */ + private void setFolderReadForAll(User user, Folder folder, Boolean readForAll){ + if (readForAll != null && user.equals(folder.getOwner())){ + folder.setReadForAll(readForAll); + dao.update(folder); + for (FileHeader file : folder.getFiles()) + file.setReadForAll(readForAll); + if(readForAll) + //only update subfolders when readforall is true. otherwise all sub-folders stay untouched + for (Folder sub : folder.getSubfolders()) + setFolderReadForAll(user, sub, readForAll); + + } + + } + + /** + * Update the userLogin with the values from the supplied object. + */ + + public void addUserLogin(UserLogin userLogin) { + dao.update(userLogin); + + } + + /** + * Retrieves the current session user login and the user's last login + * + * @param userId + * @return a list of last two user logins + * @throws ObjectNotFoundException + */ + + public List getLastUserLogins(Long userId) throws ObjectNotFoundException{ + List userLoginResults = new ArrayList(); + userLoginResults = dao.getLoginsForUser(userId); + if(userLoginResults.size() == 0) + throw new ObjectNotFoundException("No userlogin found for the user"); + //if the user logins for the first time lastLoginDate = currentLoginDate + if(userLoginResults.size()==1) + userLoginResults.add(userLoginResults.get(0)); + return userLoginResults; + } + + + @Override + public void postFileToSolr(CommonsHttpSolrServer solr, Long id) { + try { + FileHeader file = dao.getFileForIndexing(id); + FileBody body = file.getCurrentBody(); + String mime = body.getMimeType(); + boolean multipart = true; + if (!mime.equals("application/pdf") + && !mime.equals("text/plain") + && !mime.equals("text/html") + && !mime.endsWith("msword") + && !mime.endsWith("ms-excel") + && !mime.endsWith("powerpoint") + || (body.getFileSize() > getConfiguration().getLong("solrDocumentUploadLimitInKB") * 1024)) + multipart = false; + + if (!multipart) + sendMetaDataOnly(solr, file); + else { + ContentStreamUpdateRequest solrRequest = new ContentStreamUpdateRequest(getConfiguration().getString("solr.rich.update.path")); + solrRequest.setParam("literal.id", file.getId().toString()); + solrRequest.setParam("literal.name", file.getName()); + for (FileTag t : file.getFileTags()) { + solrRequest.getParams().add("literal.tag", t.getTag()); + } + for (Permission p : file.getPermissions()) { + if (p.getRead()) { + if (p.getUser() != null) + solrRequest.getParams().add("literal.ureaders", p.getUser().getId().toString()); + else if (p.getGroup() != null) + solrRequest.getParams().add("literal.greaders", p.getGroup().getId().toString()); + } + } + solrRequest.setParam("literal.owner", file.getOwner().getId().toString()); + solrRequest.setParam("literal.public", String.valueOf(file.isReadForAll())); + File fsFile = new File(body.getStoredFilePath()); + solrRequest.addFile(fsFile); + try { + solr.request(solrRequest); + } + catch (SolrException e) { + logger.warn("File " + id + " failed with SolrException: " + e.getLocalizedMessage() + ". Retrying without the file"); + //Let 's try without the file + sendMetaDataOnly(solr, file); + } + catch (NullPointerException e) { + logger.warn("File " + id + " failed with NullPointerException: " + e.getLocalizedMessage() + ". Retrying without the file"); + //Let 's try without the file + sendMetaDataOnly(solr, file); + } + catch (SolrServerException e) { + logger.warn("File " + id + " failed with SolrServerException: " + e.getLocalizedMessage() + ". Retrying without the file"); + //Let 's try without the file + sendMetaDataOnly(solr, file); + } + } + } catch (MalformedURLException e) { + throw new EJBException(e); + } catch (ObjectNotFoundException e) { + logger.error("Indexing of file id " + id + " failed.", e); + } catch (SolrServerException e) { + throw new EJBException(e); + } catch (IOException e) { + throw new EJBException(e); + } + } + + private void sendMetaDataOnly(CommonsHttpSolrServer solr, FileHeader file) throws SolrServerException, IOException { + SolrInputDocument solrDoc = new SolrInputDocument(); + solrDoc.addField("id", file.getId().toString()); + solrDoc.addField("name", file.getName()); + for (FileTag t : file.getFileTags()) { + solrDoc.addField("tag", t.getTag()); + } + for (Permission p : file.getPermissions()) { + if (p.getRead()) { + if (p.getUser() != null) + solrDoc.addField("ureaders", p.getUser().getId()); + else if (p.getGroup() != null) + solrDoc.addField("greaders", p.getGroup().getId()); + } + } + solrDoc.addField("owner", file.getOwner().getId()); + solrDoc.addField("public", file.isReadForAll()); + solr.add(solrDoc); + } + + private String tokenizeFilename(String filename){ + StringBuffer result = new StringBuffer(); + StringTokenizer tokenizer = new StringTokenizer(filename,"._"); + while(tokenizer.hasMoreTokens()){ + result.append(tokenizer.nextToken()); + result.append(" "); + } + result.append(filename); + return result.toString(); + } + + private String normalizeSearchQuery(String query) { + if (query.contains("*")) + return query.toLowerCase().replace('ά', 'α').replace('έ', 'ε').replace('ί', 'ι').replace('ή', 'η').replace('ύ', 'υ') + .replace('ό', 'ο').replace('ς', 'σ').replace('ώ', 'ω').replace('ϊ', 'ι').replace('ϋ', 'υ'); + else + return query; + } + + private String escapeCharacters(String text) { + return text.replaceAll(":", "\\\\:"); + } + + /*** NEW METHODS IN ORDER TO AVOID LAZY loading exception in json render + ****/ + @Override + public Folder expandFolder(Folder folder) throws ObjectNotFoundException{ + Folder result = dao.getEntityById(Folder.class, folder.getId()); + result.getSubfolders().size(); + result.getFiles().size(); + result.getPermissions().size(); + return result; +} + + @Override + public FileHeader expandFile(FileHeader folder) throws ObjectNotFoundException{ + FileHeader result = dao.getEntityById(FileHeader.class, folder.getId()); + result.getFolder(); + result.getPermissions().size(); + result.getFileTags().size(); + return result; + } + + @Override + public Group expandGroup(Group folder) throws ObjectNotFoundException{ + Group result = dao.getEntityById(Group.class, folder.getId()); + result.getMembers().size(); + return result; + } + + /* (non-Javadoc) + * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsersByUserNameLike(java.lang.String) + */ + @Override + public User getUserByUserName(String username) { + User result = dao.getUserByUserName(username); + return result; + } + + /*WEBDAV CREATE EMPTY FILE*/ + @Override + public FileHeader createEmptyFile(Long userId, Long folderId, String name) + throws DuplicateNameException, ObjectNotFoundException, GSSIOException, + InsufficientPermissionsException, QuotaExceededException { + // Validate. + if (userId == null) + throw new ObjectNotFoundException("No user specified"); + if (folderId == null) + throw new ObjectNotFoundException("No folder specified"); + String contentType = DEFAULT_MIME_TYPE; + if (StringUtils.isEmpty(name)) + throw new ObjectNotFoundException("No file name specified"); + if (dao.existsFolderOrFile(folderId, name)) + throw new DuplicateNameException("A folder or file with the name '" + name + + "' already exists at this level"); + + // Do the actual work. + Folder parent = null; + try { + parent = dao.getEntityById(Folder.class, folderId); + } catch (final ObjectNotFoundException onfe) { + // Supply a more accurate problem description. + throw new ObjectNotFoundException("Parent folder not found"); + } + final User owner = dao.getEntityById(User.class, userId); + if (!parent.hasWritePermission(owner)) + throw new InsufficientPermissionsException("You don't have the permissions to write to this folder"); + final FileHeader file = new FileHeader(); + file.setName(name); + parent.addFile(file); + // set file owner to folder owner + file.setOwner(parent.getOwner()); + //set file's readForAll value according to parent folder readForAll value + file.setReadForAll(parent.isReadForAll()); + + final Date now = new Date(); + final AuditInfo auditInfo = new AuditInfo(); + auditInfo.setCreatedBy(owner); + auditInfo.setCreationDate(now); + auditInfo.setModifiedBy(owner); + auditInfo.setModificationDate(now); + file.setAuditInfo(auditInfo); + // TODO set the proper versioning flag on creation + file.setVersioned(false); + + for (final Permission p : parent.getPermissions()) { + final Permission permission = new Permission(); + permission.setGroup(p.getGroup()); + permission.setUser(p.getUser()); + permission.setRead(p.getRead()); + permission.setWrite(p.getWrite()); + permission.setModifyACL(p.getModifyACL()); + file.addPermission(permission); + } + // Create the file body. + try { + createEmptyFileBody(name, contentType, 0, file, auditInfo); + } catch (FileNotFoundException e) { + throw new GSSIOException(e); + } + touchParentFolders(parent, owner, new Date()); + dao.flush(); + return file; + } + + private void createEmptyFileBody(String name, String mimeType, long fileSize, + FileHeader header, AuditInfo auditInfo) + throws FileNotFoundException, QuotaExceededException, ObjectNotFoundException { + + long currentTotalSize = 0; + if (!header.isVersioned() && header.getCurrentBody() != null && header.getBodies() != null) + currentTotalSize = header.getTotalSize(); + Long quotaLeft = getQuotaLeft(header.getOwner().getId()); + + + FileBody body = new FileBody(); + + // if no mime type or the generic mime type is defined by the client, then try to identify it from the filename extension + if (StringUtils.isEmpty(mimeType) || "application/octet-stream".equals(mimeType) + || "application/download".equals(mimeType) || "application/force-download".equals(mimeType) + || "octet/stream".equals(mimeType) || "application/unknown".equals(mimeType)) + body.setMimeType(identifyMimeType(name)); + else + body.setMimeType(mimeType); + body.setAuditInfo(auditInfo); + body.setFileSize(fileSize); + body.setOriginalFilename(name); + body.setStoredFilePath(generateRepositoryFilePath()); + //CLEAR OLD VERSION IF FILE IS NOT VERSIONED AND GETS UPDATED + if(!header.isVersioned() && header.getCurrentBody() != null){ + header.setCurrentBody(null); + if (header.getBodies() != null) { + Iterator it = header.getBodies().iterator(); + while(it.hasNext()){ + FileBody bo = it.next(); + deleteActualFile(bo.getStoredFilePath()); + it.remove(); + dao.delete(bo); + } + } + } + + dao.flush(); + header.addBody(body); + header.setAuditInfo(auditInfo); + + dao.create(body); + } + /*** WEBDAV LOCK **/ + @Override + public FileLock getLockById(String id) { + return dao.getLockById(id); + } + + @Override + public FileLock getLockByToken(String tokenId) { + return dao.getLockByToken(tokenId); + } + + @Override + public void removeLock(FileLock lock) { + dao.removeLock(lock); + } + + @Override + public FileLock saveOrUpdateLock(FileLock lock) { + return dao.saveOrUpdateLock(lock); + } + + @Override + public WebDavNonce getWebDavNonce(String tokenId) { + return dao.getWebDavNonce(tokenId); + } + + @Override + public void removeWebDavNonce(WebDavNonce nonce) { + dao.removeWebDavNonce(nonce); + } + + @Override + public WebDavNonce saveOrUpdateWebDavNonce(WebDavNonce nonce) { + return dao.saveOrUpdateWebDavNonce(nonce); + } + + /* (non-Javadoc) + * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsersByUserNameLike(java.lang.String) + */ + @Override + public UserDTO getUserByUserName(String username) { + User result = dao.getUserByUserName(username); + return result.getDTO(); + } + }