sink context menu event on empty spac
[pithos] / src / gr / ebs / gss / server / ejb / AdminAPIBean.java
1 /*
2  * Copyright 2010 Electronic Business Systems Ltd.
3  *
4  * This file is part of GSS.
5  *
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.
10  *
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.
15  *
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/>.
18  */
19 package gr.ebs.gss.server.ejb;
20
21 import gr.ebs.gss.client.exceptions.InsufficientPermissionsException;
22 import gr.ebs.gss.client.exceptions.ObjectNotFoundException;
23 import gr.ebs.gss.server.domain.AccountingInfo;
24 import gr.ebs.gss.server.domain.AuditInfo;
25 import gr.ebs.gss.server.domain.FileBody;
26 import gr.ebs.gss.server.domain.FileHeader;
27 import gr.ebs.gss.server.domain.FileUploadStatus;
28 import gr.ebs.gss.server.domain.Folder;
29 import gr.ebs.gss.server.domain.Group;
30 import gr.ebs.gss.server.domain.Permission;
31 import gr.ebs.gss.server.domain.User;
32 import gr.ebs.gss.server.domain.UserClass;
33 import gr.ebs.gss.server.domain.UserLogin;
34 import gr.ebs.gss.server.domain.dto.FileBodyDTO;
35 import gr.ebs.gss.server.domain.dto.FileHeaderDTO;
36 import gr.ebs.gss.server.domain.dto.FolderDTO;
37 import gr.ebs.gss.server.domain.dto.GroupDTO;
38 import gr.ebs.gss.server.domain.dto.PermissionDTO;
39 import gr.ebs.gss.server.domain.dto.StatsDTO;
40 import gr.ebs.gss.server.domain.dto.SystemStatsDTO;
41 import gr.ebs.gss.server.domain.dto.UserClassDTO;
42 import gr.ebs.gss.server.domain.dto.UserDTO;
43
44 import java.util.ArrayList;
45 import java.util.Calendar;
46 import java.util.Date;
47 import java.util.Iterator;
48 import java.util.LinkedHashSet;
49 import java.util.LinkedList;
50 import java.util.List;
51 import java.util.Set;
52 import java.util.StringTokenizer;
53
54 import javax.ejb.EJB;
55 import javax.ejb.Stateless;
56 import javax.jms.Connection;
57 import javax.jms.ConnectionFactory;
58 import javax.jms.JMSException;
59 import javax.jms.MapMessage;
60 import javax.jms.MessageProducer;
61 import javax.jms.Queue;
62 import javax.jms.QueueConnectionFactory;
63 import javax.jms.Session;
64 import javax.naming.Context;
65 import javax.naming.InitialContext;
66 import javax.naming.NamingException;
67
68 import org.apache.commons.lang.StringUtils;
69 import org.apache.commons.logging.Log;
70 import org.apache.commons.logging.LogFactory;
71
72 /**
73  * @author kman
74  */
75 @Stateless
76 public class AdminAPIBean implements AdminAPI {
77         /**
78          * Injected reference to the ExternalAPI service.
79          */
80         @EJB
81         private ExternalAPI api;
82
83         /**
84          * The logger.
85          */
86         private static Log logger = LogFactory.getLog(AdminAPIBean.class);
87         /**
88          * Injected reference to the GSSDAO data access facade.
89          */
90         @EJB
91         private GSSDAO dao;
92
93         @Override
94         public FileHeaderDTO getFile(String uri) throws ObjectNotFoundException {
95                 if (uri == null)
96                         throw new ObjectNotFoundException("No uri specified");
97
98                 List<String> pathElements = new ArrayList<String>();
99                 StringTokenizer st = new StringTokenizer(uri, "/");
100                 String username = st.nextToken();
101                 st.nextToken();
102                 while (st.hasMoreTokens())
103                         pathElements.add(st.nextToken());
104                 if (pathElements.size() < 1)
105                         throw new ObjectNotFoundException("No file found");
106                 User owner = dao.getUser(username);
107                 // Store the last element, since it requires special handling.
108                 String lastElement = pathElements.remove(pathElements.size() - 1);
109                 FolderDTO cursor = api.getRootFolder(owner.getId());
110                 // Traverse and verify the specified folder path.
111                 for (String pathElement : pathElements) {
112                         cursor = getFolder(cursor.getId(), pathElement);
113                         if (cursor.isDeleted())
114                                 throw new ObjectNotFoundException("Folder " + cursor.getPath() + " not found");
115                 }
116                 FileHeaderDTO file = getFile(cursor.getId(), lastElement);
117                 return file;
118         }
119
120         @Override
121         public List<FileHeaderDTO> getFiles(String uri) throws ObjectNotFoundException, InsufficientPermissionsException {
122                 if (uri == null)
123                         throw new ObjectNotFoundException("No uri specified");
124                 List<FileHeaderDTO> res = new ArrayList<FileHeaderDTO>();
125                 List<String> pathElements = new ArrayList<String>();
126                 StringTokenizer st = new StringTokenizer(uri, "/");
127                 if(st.countTokens()<2)
128                         return res;
129                 String username = st.nextToken();
130                 st.nextToken();
131                 User owner = dao.getUser(username);
132                 while (st.hasMoreTokens())
133                         pathElements.add(st.nextToken());
134                 if (pathElements.size() < 1){
135
136                                 FolderDTO folder = api.getRootFolder(owner.getId());
137                                 res.addAll(api.getFiles(folder.getOwner().getId(), folder.getId(), false));
138                                 return res;
139                 }
140
141                 // Store the last element, since it requires special handling.
142                 String lastElement = pathElements.remove(pathElements.size() - 1);
143                 FolderDTO cursor = api.getRootFolder(owner.getId());
144                 // Traverse and verify the specified folder path.
145                 for (String pathElement : pathElements) {
146                         cursor = getFolder(cursor.getId(), pathElement);
147                         if (cursor.isDeleted())
148                                 throw new ObjectNotFoundException("Folder " + cursor.getPath() + " not found");
149                 }
150                 try {
151                         FileHeaderDTO file = getFile(cursor.getId(), lastElement);
152                         res.add(file);
153                 } catch (ObjectNotFoundException e) {
154                         // Perhaps the requested resource is not a file, so
155                         // check for folders as well.
156                         FolderDTO folder = getFolder(cursor.getId(), lastElement);
157                         res.addAll(api.getFiles(folder.getOwner().getId(), folder.getId(), false));
158
159                 }
160
161                 return res;
162         }
163
164         private FolderDTO getFolder(Long parentId, String name) throws ObjectNotFoundException {
165                 if (parentId == null)
166                         throw new ObjectNotFoundException("No parent folder specified");
167                 if (StringUtils.isEmpty(name))
168                         throw new ObjectNotFoundException("No folder specified");
169
170                 Folder folder = dao.getFolder(parentId, name);
171                 return folder.getDTO();
172         }
173
174         private FileHeaderDTO getFile(Long folderId, String name) throws ObjectNotFoundException {
175                 if (folderId == null)
176                         throw new ObjectNotFoundException("No parent folder specified");
177                 if (StringUtils.isEmpty(name))
178                         throw new ObjectNotFoundException("No file specified");
179
180                 FileHeader file = dao.getFile(folderId, name);
181                 FileHeaderDTO dto = file.getDTO();
182                 Set<Permission> perms = file.getPermissions();
183                 Set<PermissionDTO> result = new LinkedHashSet<PermissionDTO>();
184                 for (Permission perm : perms)
185                         if (perm.getUser() != null && perm.getUser().getId().equals(file.getOwner().getId()))
186                                 result.add(perm.getDTO());
187                 for (Permission perm : perms)
188                         if (perm.getUser() != null && perm.getUser().getId().equals(file.getOwner().getId())) {
189                         } else
190                                 result.add(perm.getDTO());
191                 dto.setPermissions(result);
192                 return dto;
193         }
194         @Override
195         public FileHeaderDTO getFile(Long fileId) throws ObjectNotFoundException {
196                 FileHeader file = dao.getEntityById(FileHeader.class, fileId);
197                 FileHeaderDTO dto = file.getDTO();
198                 Set<Permission> perms = file.getPermissions();
199                 Set<PermissionDTO> result = new LinkedHashSet<PermissionDTO>();
200                 for (Permission perm : perms)
201                         if (perm.getUser() != null && perm.getUser().getId().equals(file.getOwner().getId()))
202                                 result.add(perm.getDTO());
203                 for (Permission perm : perms)
204                         if (perm.getUser() != null && perm.getUser().getId().equals(file.getOwner().getId())) {
205                         } else
206                                 result.add(perm.getDTO());
207                 dto.setPermissions(result);
208                 return dto;
209         }
210
211         @Override
212         public UserDTO getUser(Long userId) throws ObjectNotFoundException {
213                 return api.getUserDTO(userId);
214         }
215
216         @Override
217         public StatsDTO getUserStatistics(Long userId) throws ObjectNotFoundException {
218                 StatsDTO stats = api.getUserStatistics(userId);
219                 User user = dao.getEntityById(User.class, userId);
220                 AccountingInfo info = dao.getAccountingInfo(user, new Date());
221                 stats.setBandwithQuotaUsed(info.getBandwidthUsed());
222                 return stats;
223         }
224
225         @Override
226         public List<UserDTO> searchUsers(String query) throws ObjectNotFoundException {
227                 List<User> users = dao.getUsersByUserNameOrEmailLike(query);
228                 List<UserDTO> result = new ArrayList<UserDTO>();
229                 for (User u : users){
230                         UserDTO tempDTO = u.getDTO();
231                         List<UserLogin> userLogins = api.getLastUserLogins(u.getId());
232                         tempDTO.setCurrentLoginDate(userLogins.get(0).getLoginDate());
233                         tempDTO.setLastLoginDate(userLogins.get(1).getLoginDate());     
234                         result.add(tempDTO);
235                 }
236                 return result;
237         }
238
239         @Override
240         public UserDTO getUser(String username) throws ObjectNotFoundException{
241                 User u = dao.getUser(username);
242                 if(u!=null){
243                         UserDTO tempDTO = u.getDTO();
244                         List<UserLogin> userLogins = api.getLastUserLogins(u.getId());
245                         tempDTO.setCurrentLoginDate(userLogins.get(0).getLoginDate());
246             tempDTO.setLastLoginDate(userLogins.get(1).getLoginDate());
247                         return tempDTO;
248                         
249                 }
250                 return null;
251         }
252         @Override
253         public void toggleActiveUser(Long userId) throws ObjectNotFoundException {
254                 User user = dao.getEntityById(User.class, userId);
255                 user.setActive(!user.isActive());
256                 dao.update(user);
257         }
258
259         @Override
260         public void setFilePermissions(String uri, Set<PermissionDTO> permissions)
261                         throws ObjectNotFoundException {
262                 FileHeaderDTO filedto = getFile(uri);
263                 FileHeader file = dao.getEntityById(FileHeader.class, filedto.getId());
264                 if (permissions != null && !permissions.isEmpty()) {
265                         // Send e-mails to the users that are granted new permissions on the file
266                         // Delete previous entries.
267                         for (Permission perm: file.getPermissions())
268                                 dao.delete(perm);
269                         file.getPermissions().clear();
270                         for (PermissionDTO dto : permissions) {
271                                 //if (dto.getUser()!=null && dto.getUser().getId().equals(file.getOwner().getId()) && (!dto.hasRead() || !dto.hasWrite() || !dto.hasModifyACL()))
272                                         //throw new InsufficientPermissionsException("Can't remove permissions from owner");
273                                 // Don't include 'empty' permission.
274                                 if (!dto.getRead() && !dto.getWrite() && !dto.getModifyACL()) continue;
275                                 file.addPermission(getPermission(dto));
276                         }
277                         dao.flush();
278                 }
279         }
280
281         private Permission getPermission(PermissionDTO dto) throws ObjectNotFoundException {
282                 Permission res = new Permission();
283                 if (dto.getGroup() != null)
284                         res.setGroup(dao.getEntityById(Group.class, dto.getGroup().getId()));
285                 else if (dto.getUser() != null)
286                         if (dto.getUser().getId() == null)
287                                 res.setUser(dao.getUser(dto.getUser().getUsername()));
288                         else
289                                 res.setUser(dao.getEntityById(User.class, dto.getUser().getId()));
290                 res.setRead(dto.hasRead());
291                 res.setWrite(dto.hasWrite());
292                 res.setModifyACL(dto.hasModifyACL());
293                 return res;
294         }
295
296         @Override
297         public SystemStatsDTO getSystemStatistics() {
298                 SystemStatsDTO statistics = new SystemStatsDTO();
299                 List<UserClass> uclasses = dao.getUserClasses();
300                 for (UserClass u : uclasses){
301                         UserClassDTO dto = u.getDTOWithoutUsers();
302                         SystemStatsDTO stats = new SystemStatsDTO();
303                         stats.setFileCount(dao.getFileCount(u));
304                         stats.setFileSize(dao.getFileSize(u));
305                         stats.setUserCount(dao.getUserCount(u));
306                         stats.setBandwithUsed(dao.getBandwithUsed(u, new Date()));
307                         dto.setStatistics(stats);
308                         statistics.getUserClasses().add(dto);
309
310                 }
311                 Calendar now = Calendar.getInstance();
312                 now.add(Calendar.DAY_OF_MONTH, -7);
313                 Date week = now.getTime();
314                 now=Calendar.getInstance();
315                 now.add(Calendar.MONTH, -1);
316                 Date month = now.getTime();
317                 statistics.setLastMonthUsers(dao.getCountUsersByLastLogin(month));
318                 statistics.setLastWeekUsers(dao.getCountUsersByLastLogin(week));
319                 statistics.setFileCount(dao.getFileCount((UserClass)null));
320                 statistics.setFileSize(dao.getFileSize((UserClass)null));
321                 statistics.setUserCount(dao.getUserCount((UserClass)null));
322                 statistics.setBandwithUsed(dao.getBandwithUsed(null, new Date()));
323                 return statistics;
324         }
325
326         @Override
327         public List<UserDTO> getLastLoggedInUsers(Date lastLoginDate) {
328                 List<User> users = dao.getUsersByLastLogin(lastLoginDate);
329                 List<UserDTO> result = new ArrayList<UserDTO>();
330                 for (User u : users){                   
331                         UserDTO tempDTO = u.getDTO();
332                         List<UserLogin> userLogins = dao.getLoginsForUser(u.getId());
333                         tempDTO.setCurrentLoginDate(userLogins.get(0).getLoginDate());
334                         tempDTO.setLastLoginDate(userLogins.get(1).getLoginDate());                     
335                         result.add(tempDTO);
336                 }
337                 return result;
338         }
339         
340         @Override
341         public List<FileBodyDTO> getVersions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
342                 if (userId == null)
343                         throw new ObjectNotFoundException("No user specified");
344                 if (fileId == null)
345                         throw new ObjectNotFoundException("No file specified");
346                 User user = dao.getEntityById(User.class, userId);
347                 FileHeader header = dao.getEntityById(FileHeader.class, fileId);
348                 List<FileBodyDTO> result = new LinkedList<FileBodyDTO>();
349                 for(int i = header.getBodies().size()-1 ; i>=0; i--)
350                         result.add(header.getBodies().get(i).getDTO());
351                 return result;
352         }
353         @Override
354         public List<UserDTO> getUsersWaitingActivation(){
355                 List<User> users = dao.getInactiveUsers();
356                 List<UserDTO> result = new ArrayList<UserDTO>();
357                 for(User u :users){
358                         UserDTO tempDTO = u.getDTO();
359                         List<UserLogin> userLogins = dao.getLoginsForUser(u.getId());
360                         tempDTO.setCurrentLoginDate(userLogins.get(0).getLoginDate());
361                         tempDTO.setLastLoginDate(userLogins.get(1).getLoginDate());     
362                         result.add(tempDTO);
363                         
364                 }
365                 return result;
366         }
367
368         @Override
369         public void changeUserClass(Long userId, Long userClassId) throws ObjectNotFoundException{
370                 User user = dao.getEntityById(User.class, userId);
371                 UserClass userClass = dao.getEntityById(UserClass.class, userClassId);
372                 user.setUserClass(userClass);
373                 dao.update(user);
374         }
375
376         @Override
377         public List<UserClassDTO> getUserClasses(){
378                 List<UserClassDTO> result = new ArrayList<UserClassDTO>();
379                 for(UserClass c : dao.getUserClasses())
380                         result.add(c.getDTOWithoutUsers());
381                 return result;
382         }
383
384         @Override
385         public void saveOrUpdateUserClass(UserClassDTO dto) throws ObjectNotFoundException{
386                 UserClass uclass;
387                 if(dto.getId()!=null)
388                         uclass = dao.getEntityById(UserClass.class, dto.getId());
389                 else
390                         uclass = new UserClass();
391                 uclass.setName(dto.getName());
392                 uclass.setQuota(dto.getQuota());
393                 if(dto.getId()!=null)
394                         dao.update(uclass);
395                 else
396                         dao.create(uclass);
397                 dao.flush();
398
399         }
400
401         @Override
402         public void removeUserClass(UserClassDTO dto) throws ObjectNotFoundException{
403                 UserClass uclass = dao.getEntityById(UserClass.class, dto.getId());
404                 if(uclass==null)
405                         throw new ObjectNotFoundException("User Class not found");
406                 dao.delete(uclass);
407         }
408
409         @Override
410         public List<FileHeaderDTO> searchFileByFilename(String fileName){
411                 List<FileHeader> files = dao.searchFileByFilename(fileName);
412                 List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
413                 for(FileHeader h : files)
414                         result.add(h.getDTO());
415                 return result;
416         }
417
418         @Override
419         public void removeUser(Long userId) throws ObjectNotFoundException, InsufficientPermissionsException{
420                 User user = api.getUser(userId);
421                 try{
422                         FolderDTO folder = api.getRootFolder(userId);
423                         deleteFolder(userId, folder.getId());
424                         List<GroupDTO> groups = api.getGroups(userId);
425                         for(GroupDTO group : groups)
426                                 api.deleteGroup(userId, group.getId());
427                 }
428                 catch(ObjectNotFoundException e){}
429                 List<Folder> otherFolders = dao.getSharingFoldersForUser(userId);
430                 for(Folder f : otherFolders){
431                         Iterator<Permission> pit = f.getPermissions().iterator();
432                         while(pit.hasNext()){
433                                 Permission p = pit.next();
434                                 if(p.getUser()!=null&&p.getUser().getId().equals(userId)){
435                                         pit.remove();
436                                         dao.delete(p);
437                                 }
438                         }
439                         dao.update(f);
440                 }
441                 List<FileHeader> otherFiles = dao.getSharingFilesForUser(userId);
442                 for(FileHeader f : otherFiles){
443                         Iterator<Permission> pit = f.getPermissions().iterator();
444                         while(pit.hasNext()){
445                                 Permission p = pit.next();
446                                 if(p.getUser()!=null&&p.getUser().getId().equals(userId)){
447                                         pit.remove();
448                                         dao.delete(p);
449                                 }
450                         }
451                         dao.update(f);
452                 }
453                 List<Group> otherGroups = dao.getGroupsContainingUser(userId);
454                 for(Group g : otherGroups){
455                         Iterator<User> uit = g.getMembers().iterator();
456                         while(uit.hasNext()){
457                                 User u = uit.next();
458                                 if(u.getId().equals(userId)){
459                                         uit.remove();
460                                 }
461                         }
462                         dao.update(g);
463                 }
464                 List<AccountingInfo> infos = dao.getAccountingInfo(user);
465                 Iterator<AccountingInfo> it = infos.iterator();
466                 while(it.hasNext()){
467                         AccountingInfo a = it.next();
468                         dao.delete(a);
469                 }
470                 List<FileUploadStatus> sts = dao.getUploadStatus(userId);
471                 for(FileUploadStatus s : sts)
472                         dao.delete(s);
473                 int deleteCount=dao.deletePermissionsNotCorrespondingToFilesAndFolders(userId);
474                 
475                 List<UserLogin> allUserLogins = dao.getAllLoginsForUser(userId);
476                 for(UserLogin ul : allUserLogins)
477                         dao.delete(ul);
478                 dao.flush();
479                 dao.delete(user);
480         }
481
482         /**
483          * Deletes the given folder and all its subfolders and files
484          * Only the permissions for top folder are checked
485          *
486          * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteFolder(java.lang.Long,
487          *      java.lang.Long)
488          */
489         public void deleteFolder(final Long userId, final Long folderId) throws ObjectNotFoundException {
490                 // Validate.
491                 if (userId == null)
492                         throw new ObjectNotFoundException("No user specified");
493                 if (folderId == null)
494                         throw new ObjectNotFoundException("No folder specified");
495
496                 // Do the actual work.
497                 final Folder folder = dao.getEntityById(Folder.class, folderId);
498                 final Folder parent = folder.getParent();
499                 final User user = dao.getEntityById(User.class, userId);
500
501                 removeSubfolderFiles(folder);
502                 if(parent!=null)
503                         parent.removeSubfolder(folder);
504                 dao.delete(folder);
505                 if(parent!=null)
506                         touchParentFolders(parent, user, new Date());
507         }
508
509         private void removeSubfolderFiles(Folder folder) {
510                 //remove files for all subfolders
511                 for (Folder subfolder:folder.getSubfolders())
512                         removeSubfolderFiles(subfolder);
513                 //remove this folder's file bodies (actual files)
514                 for (FileHeader file:folder.getFiles()) {
515                         for (FileBody body:file.getBodies())
516                                 api.deleteActualFile(body.getStoredFilePath());
517                         indexFile(file.getId(), true);
518                 }
519         }
520
521         private void touchParentFolders(Folder folder, User modifiedBy, Date modificationDate) {
522                 Folder f = folder;
523                 while (f!=null) {
524                         AuditInfo ai = f.getAuditInfo();
525                         ai.setModifiedBy(modifiedBy);
526                         ai.setModificationDate(modificationDate);
527                         f.setAuditInfo(ai);
528                         f = f.getParent();
529                 }
530         }
531
532         public void indexFile(Long fileId, boolean delete) {
533                 Connection qConn = null;
534                 Session session = null;
535                 MessageProducer sender = null;
536                 try {
537                         Context jndiCtx = new InitialContext();
538                         ConnectionFactory factory = (QueueConnectionFactory) jndiCtx.lookup("java:/JmsXA");
539                         Queue queue = (Queue) jndiCtx.lookup("queue/gss-indexingQueue");
540                         qConn = factory.createConnection();
541                         session = qConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
542                         sender = session.createProducer(queue);
543
544                         MapMessage map = session.createMapMessage();
545                         map.setObject("id", fileId);
546                         map.setBoolean("delete", delete);
547                         sender.send(map);
548                 }
549                 catch (NamingException e) {
550                         logger.error("Index was not updated: ", e);
551                 }
552                 catch (JMSException e) {
553                         logger.error("Index was not updated: ", e);
554                 }
555                 finally {
556                         try {
557                                 if (sender != null)
558                                         sender.close();
559                                 if (session != null)
560                                         session.close();
561                                 if (qConn != null)
562                                         qConn.close();
563                         }
564                         catch (JMSException e) {
565                                 logger.warn(e);
566                         }
567                 }
568         }
569
570 }