Revision d805967a

b/gss/src/gr/ebs/gss/client/FolderPropertiesDialog.java
344 344
				}
345 345
				else
346 346
					GSS.get().displayError("System error moifying file: "+t.getMessage());
347
				GSS.get().getFolders().updateFolder( (DnDTreeItem) GSS.get().getFolders().getCurrent());
347 348
			}
348 349
		};
349 350
		DeferredCommand.addCommand(ep);
b/gss/src/gr/ebs/gss/client/PermissionsList.java
108 108
			write.setChecked(dto.isWrite());
109 109
			CheckBox modify = new CheckBox();
110 110
			modify.setChecked(dto.isModifyACL());
111
			if (dto.getUser()!=null && dto.getUser().equals(owner)) {
112
				read.setEnabled(false);
113
				write.setEnabled(false);
114
				modify.setEnabled(false);
115
			}
111 116
			permTable.setWidget(i, 1, read);
112 117
			permTable.setWidget(i, 2, write);
113 118
			permTable.setWidget(i, 3, modify);
b/gss/src/gr/ebs/gss/client/exceptions/InsufficientPermissionsException.java
20 20

  
21 21
import java.io.Serializable;
22 22

  
23
import javax.ejb.ApplicationException;
24

  
23 25
/**
24 26
 * An exception that is thrown when an operation cannot be performed due to the
25 27
 * user having insufficient permissions.
26 28
 *
27 29
 * @author chstath
28 30
 */
31
@ApplicationException(rollback=true)
29 32
public class InsufficientPermissionsException extends Exception implements Serializable {
30 33

  
31 34
	/**
b/gss/src/gr/ebs/gss/server/ejb/ExternalAPIBean.java.tmp
1
/*
2
 * Copyright 2007, 2008, 2009 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 static gr.ebs.gss.server.configuration.GSSConfigurationFactory.getConfiguration;
22
import gr.ebs.gss.client.exceptions.DuplicateNameException;
23
import gr.ebs.gss.client.exceptions.GSSIOException;
24
import gr.ebs.gss.client.exceptions.InsufficientPermissionsException;
25
import gr.ebs.gss.client.exceptions.ObjectNotFoundException;
26
import gr.ebs.gss.client.exceptions.QuotaExceededException;
27
import gr.ebs.gss.server.domain.AuditInfo;
28
import gr.ebs.gss.server.domain.FileBody;
29
import gr.ebs.gss.server.domain.FileHeader;
30
import gr.ebs.gss.server.domain.FileTag;
31
import gr.ebs.gss.server.domain.FileUploadStatus;
32
import gr.ebs.gss.server.domain.Folder;
33
import gr.ebs.gss.server.domain.Group;
34
import gr.ebs.gss.server.domain.Nonce;
35
import gr.ebs.gss.server.domain.Permission;
36
import gr.ebs.gss.server.domain.User;
37
import gr.ebs.gss.server.domain.dto.FileBodyDTO;
38
import gr.ebs.gss.server.domain.dto.FileHeaderDTO;
39
import gr.ebs.gss.server.domain.dto.FolderDTO;
40
import gr.ebs.gss.server.domain.dto.GroupDTO;
41
import gr.ebs.gss.server.domain.dto.PermissionDTO;
42
import gr.ebs.gss.server.domain.dto.StatsDTO;
43
import gr.ebs.gss.server.domain.dto.UserDTO;
44

  
45
import java.io.File;
46
import java.io.FileInputStream;
47
import java.io.FileNotFoundException;
48
import java.io.FileOutputStream;
49
import java.io.IOException;
50
import java.io.InputStream;
51
import java.io.StringWriter;
52
import java.io.UnsupportedEncodingException;
53
import java.util.ArrayList;
54
import java.util.Date;
55
import java.util.Iterator;
56
import java.util.LinkedHashSet;
57
import java.util.LinkedList;
58
import java.util.List;
59
import java.util.Random;
60
import java.util.Set;
61
import java.util.StringTokenizer;
62

  
63
import javax.ejb.EJB;
64
import javax.ejb.EJBException;
65
import javax.ejb.Stateless;
66
import javax.ejb.TransactionAttribute;
67
import javax.ejb.TransactionAttributeType;
68
import javax.jms.Connection;
69
import javax.jms.ConnectionFactory;
70
import javax.jms.JMSException;
71
import javax.jms.MapMessage;
72
import javax.jms.MessageProducer;
73
import javax.jms.Queue;
74
import javax.jms.QueueConnectionFactory;
75
import javax.jms.Session;
76
import javax.jws.WebMethod;
77
import javax.naming.Context;
78
import javax.naming.InitialContext;
79
import javax.naming.NamingException;
80
import javax.xml.parsers.DocumentBuilder;
81
import javax.xml.parsers.DocumentBuilderFactory;
82
import javax.xml.parsers.ParserConfigurationException;
83
import javax.xml.transform.OutputKeys;
84
import javax.xml.transform.Transformer;
85
import javax.xml.transform.TransformerConfigurationException;
86
import javax.xml.transform.TransformerException;
87
import javax.xml.transform.TransformerFactory;
88
import javax.xml.transform.dom.DOMSource;
89
import javax.xml.transform.stream.StreamResult;
90

  
91
import org.apache.commons.httpclient.HttpClient;
92
import org.apache.commons.httpclient.HttpException;
93
import org.apache.commons.httpclient.NameValuePair;
94
import org.apache.commons.httpclient.methods.GetMethod;
95
import org.apache.commons.httpclient.methods.PostMethod;
96
import org.apache.commons.httpclient.methods.StringRequestEntity;
97
import org.apache.commons.lang.StringUtils;
98
import org.apache.commons.logging.Log;
99
import org.apache.commons.logging.LogFactory;
100
import org.w3c.dom.DOMException;
101
import org.w3c.dom.Document;
102
import org.w3c.dom.Node;
103
import org.w3c.dom.NodeList;
104
import org.xml.sax.SAXException;
105

  
106
/**
107
 * The concrete implementation of the ExternalAPI interface.
108
 *
109
 * @author past
110
 */
111
@Stateless
112
public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote {
113
	/**
114
	 * The default MIME type for files without an explicit one.
115
	 */
116
	private static final String DEFAULT_MIME_TYPE = "application/octet-stream";
117

  
118
	/**
119
	 * The size of the buffer that is used to temporarily store chunks of
120
	 * uploaded files, while storing them to the file repository.
121
	 */
122
	private static final int UPLOAD_BUFFER_SIZE = 1024 * 4;
123

  
124
	/**
125
	 * The logger.
126
	 */
127
	private static Log logger = LogFactory.getLog(ExternalAPIBean.class);
128

  
129
	/**
130
	 * Injected reference to the GSSDAO data access facade.
131
	 */
132
	@EJB
133
	private GSSDAO dao;
134

  
135

  
136
	/**
137
	 * A cached random number generator for creating unique filenames.
138
	 */
139
	private static Random random = new Random();
140

  
141
	@Override
142
	public FolderDTO getRootFolder(Long userId) throws ObjectNotFoundException {
143
		if (userId == null)
144
			throw new ObjectNotFoundException("No user specified");
145
		Folder folder = dao.getRootFolder(userId);
146
		return folder.getDTO();
147
	}
148

  
149
	/*
150
	 * (non-Javadoc)
151
	 *
152
	 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFolder(java.lang.Long)
153
	 */
154
	public FolderDTO getFolder(final Long userId, final Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
155
		if (userId == null)
156
			throw new ObjectNotFoundException("No user specified");
157
		if (folderId == null)
158
			throw new ObjectNotFoundException("No folder specified");
159
		final User user = dao.getEntityById(User.class, userId);
160
		final Folder folder = dao.getEntityById(Folder.class, folderId);
161
		// Check permissions
162
		if (!folder.hasReadPermission(user))
163
			throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
164
		return folder.getDTO();
165
	}
166

  
167
	/* (non-Javadoc)
168
	 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUser(java.lang.Long)
169
	 */
170
	public User getUser(Long userId) throws ObjectNotFoundException {
171
		if (userId == null)
172
			throw new ObjectNotFoundException("No user specified");
173
		return dao.getEntityById(User.class, userId);
174
	}
175

  
176
	/* (non-Javadoc)
177
	 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUserDTO(java.lang.Long)
178
	 */
179
	public UserDTO getUserDTO(final Long userId) throws ObjectNotFoundException {
180
		return getUser(userId).getDTO();
181
	}
182

  
183
	/*
184
	 * (non-Javadoc)
185
	 *
186
	 * @see gr.ebs.gss.server.ejb.ExternalAPI#getGroup(java.lang.Long)
187
	 */
188
	public GroupDTO getGroup(final Long groupId) throws ObjectNotFoundException {
189
		if (groupId == null)
190
			throw new ObjectNotFoundException("No group specified");
191
		final Group group = dao.getEntityById(Group.class, groupId);
192
		return group.getDTO();
193
	}
194

  
195
	@Override
196
	public GroupDTO getGroup(Long userId, String name) throws ObjectNotFoundException {
197
		if (userId == null)
198
			throw new ObjectNotFoundException("No user specified");
199
		if (name == null)
200
			throw new ObjectNotFoundException("No group specified");
201
		User user = dao.getEntityById(User.class, userId);
202
		List<Group> groups = user.getGroupsSpecified();
203
		for (Group group: groups)
204
			if (group.getName().equals(name))
205
				return group.getDTO();
206
		throw new ObjectNotFoundException("Group " + name + " not found");
207
	}
208

  
209
	/*
210
	 * (non-Javadoc)
211
	 *
212
	 * @see gr.ebs.gss.server.ejb.ExternalAPI#getGroups(java.lang.Long)
213
	 */
214
	public List<GroupDTO> getGroups(final Long userId) throws ObjectNotFoundException {
215
		if (userId == null)
216
			throw new ObjectNotFoundException("No user specified");
217
		final List<Group> groups = dao.getGroups(userId);
218
		final List<GroupDTO> result = new ArrayList<GroupDTO>();
219
		for (final Group g : groups)
220
			result.add(g.getDTO());
221
		return result;
222
	}
223

  
224
	@Override
225
	public List<FileHeaderDTO> getFiles(Long userId, Long folderId, boolean ignoreDeleted)
226
			throws ObjectNotFoundException, InsufficientPermissionsException {
227
		// Validate.
228
		if (userId == null)
229
			throw new ObjectNotFoundException("No user specified");
230
		if (folderId == null)
231
			throw new ObjectNotFoundException("No folder specified");
232
		User user = dao.getEntityById(User.class, userId);
233
		Folder folder = dao.getEntityById(Folder.class, folderId);
234
		if (!folder.hasReadPermission(user))
235
			throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
236
		// Do the actual work.
237
		List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
238
		List<FileHeader> files = dao.getFiles(folderId, ignoreDeleted);
239
		for (FileHeader f : files)
240
			result.add(f.getDTO());
241
		return result;
242
	}
243

  
244
	/*
245
	 * (non-Javadoc)
246
	 *
247
	 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsers(java.lang.Long,
248
	 *      java.lang.Long)
249
	 */
250
	public List<UserDTO> getUsers(final Long userId, final Long groupId) throws ObjectNotFoundException {
251
		// Validate.
252
		if (userId == null)
253
			throw new ObjectNotFoundException("No user specified");
254
		if (groupId == null)
255
			throw new ObjectNotFoundException("No group specified");
256

  
257
		// Do the actual work.
258
		final List<User> users = dao.getUsers(groupId);
259
		final List<UserDTO> result = new ArrayList<UserDTO>();
260
		for (final User u : users)
261
			result.add(u.getDTO());
262
		return result;
263
	}
264

  
265
	@Override
266
	public void createFolder(Long userId, Long parentId, String name)
267
			throws DuplicateNameException, ObjectNotFoundException, InsufficientPermissionsException {
268
		// Validate.
269
		if (userId == null)
270
			throw new ObjectNotFoundException("No user specified");
271
		if (StringUtils.isEmpty(name))
272
			throw new ObjectNotFoundException("New folder name is empty");
273
		if (parentId == null)
274
			throw new ObjectNotFoundException("No parent specified");
275
		if (dao.existsFolderOrFile(parentId, name))
276
			throw new DuplicateNameException("A folder or file with the name '" +
277
						name + "' already exists at this level");
278

  
279
		User creator = dao.getEntityById(User.class, userId);
280

  
281
		Folder parent = null;
282
		try {
283
			parent = dao.getEntityById(Folder.class, parentId);
284
		} catch (ObjectNotFoundException onfe) {
285
			// Supply a more accurate problem description.
286
			throw new ObjectNotFoundException("Parent folder not found");
287
		}
288
		if (!parent.hasWritePermission(creator))
289
			throw new InsufficientPermissionsException("You don't have the permissions" +
290
					" to write to this folder");
291

  
292
		// Do the actual work.
293
		createFolder(name, parent, creator);
294
	}
295

  
296
	/**
297
	 * Create a new folder with the provided name, parent and owner.
298
	 *
299
	 * @param name
300
	 * @param parent
301
	 * @param creator
302
	 * @param owner
303
	 */
304
	private void createFolder(String name, Folder parent, User creator) {
305
		Folder folder = new Folder();
306
		folder.setName(name);
307
		if (parent != null) {
308
			parent.addSubfolder(folder);
309
			folder.setOwner(parent.getOwner());
310
		} else
311
			folder.setOwner(creator);
312

  
313
		Date now = new Date();
314
		AuditInfo auditInfo = new AuditInfo();
315
		auditInfo.setCreatedBy(creator);
316
		auditInfo.setCreationDate(now);
317
		auditInfo.setModifiedBy(creator);
318
		auditInfo.setModificationDate(now);
319
		folder.setAuditInfo(auditInfo);
320

  
321
		if (parent != null)
322
			for (Permission p : parent.getPermissions()) {
323
				Permission permission = new Permission();
324
				permission.setGroup(p.getGroup());
325
				permission.setUser(p.getUser());
326
				permission.setRead(p.getRead());
327
				permission.setWrite(p.getWrite());
328
				permission.setModifyACL(p.getModifyACL());
329
				folder.addPermission(permission);
330
			}
331
		else {
332
			Permission permission = new Permission();
333
			permission.setUser(creator);
334
			permission.setRead(true);
335
			permission.setWrite(true);
336
			permission.setModifyACL(true);
337
			folder.addPermission(permission);
338
		}
339
		dao.create(folder);
340
	}
341

  
342
	/*
343
	 * (non-Javadoc)
344
	 *
345
	 * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteFolder(java.lang.Long,
346
	 *      java.lang.Long)
347
	 */
348
	public void deleteFolder(final Long userId, final Long folderId) throws InsufficientPermissionsException, ObjectNotFoundException {
349
		// Validate.
350
		if (userId == null)
351
			throw new ObjectNotFoundException("No user specified");
352
		if (folderId == null)
353
			throw new ObjectNotFoundException("No folder specified");
354

  
355
		// Do the actual work.
356
		final Folder folder = dao.getEntityById(Folder.class, folderId);
357
		final Folder parent = folder.getParent();
358
		if (parent == null)
359
			throw new ObjectNotFoundException("Deleting the root folder is not allowed");
360
		final User user = dao.getEntityById(User.class, userId);
361
		if (!folder.hasDeletePermission(user)) {
362
			logger.info("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
363
			throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
364
		}
365
		parent.removeSubfolder(folder);
366
		dao.delete(folder);
367
	}
368

  
369
	@SuppressWarnings("unchecked")
370
	public List<FolderDTO> getSubfolders(Long userId, Long folderId)
371
			throws ObjectNotFoundException, InsufficientPermissionsException {
372
		if (userId == null)
373
			throw new ObjectNotFoundException("No user specified");
374
		if (folderId == null)
375
			throw new ObjectNotFoundException("No folder specified");
376
		User user = dao.getEntityById(User.class, userId);
377
		Folder folder = dao.getEntityById(Folder.class, folderId);
378
		if (!folder.hasReadPermission(user))
379
			throw new InsufficientPermissionsException("You don't have the permissions to read this folder");
380
		List<FolderDTO> result = new ArrayList<FolderDTO>();
381
		if (folder.hasReadPermission(user))
382
			for (Folder f : folder.getSubfolders())
383
				if (f.hasReadPermission(user) && !f.isDeleted())
384
					result.add(f.getDTO());
385
		return result;
386
	}
387

  
388
	@Override
389
	public void modifyFolder(Long userId, Long folderId, String folderName)
390
			throws InsufficientPermissionsException, ObjectNotFoundException, DuplicateNameException {
391

  
392
		// Validate.
393
		if (userId == null)
394
			throw new ObjectNotFoundException("No user specified");
395
		if (folderId == null)
396
			throw new ObjectNotFoundException("No folder specified");
397
		if (StringUtils.isEmpty(folderName))
398
			throw new ObjectNotFoundException("New folder name is empty");
399

  
400
		Folder folder = dao.getEntityById(Folder.class, folderId);
401
		User user = dao.getEntityById(User.class, userId);
402
		if (!folder.hasWritePermission(user))
403
			throw new InsufficientPermissionsException("You don't have the necessary permissions");
404

  
405
		Folder parent = folder.getParent();
406
		if (parent != null)
407
			if (!folder.getName().equals(folderName) && dao.existsFolderOrFile(parent.getId(), folderName))
408
				throw new DuplicateNameException("A folder or file with the name '" + folderName + "' already exists at this level");
409

  
410
		// Do the actual modification.
411
		folder.setName(folderName);
412
		dao.update(folder);
413
	}
414

  
415
	/*
416
	 * (non-Javadoc)
417
	 *
418
	 * @see gr.ebs.gss.server.ejb.ExternalAPI#createGroup(java.lang.Long,
419
	 *      java.lang.String)
420
	 */
421
	public void createGroup(final Long userId, final String name) throws ObjectNotFoundException, DuplicateNameException {
422
		// Validate.
423
		if (userId == null)
424
			throw new ObjectNotFoundException("No user specified");
425
		if (StringUtils.isEmpty(name))
426
			throw new ObjectNotFoundException("New group name is empty");
427
		if (dao.existsGroup(userId, name))
428
			throw new DuplicateNameException("A group with the name '" + name + "' already exists");
429

  
430
		// TODO: Check permissions
431

  
432
		final User owner = dao.getEntityById(User.class, userId);
433

  
434
		// Do the actual work.
435
		owner.createGroup(name);
436
	}
437

  
438
	/*
439
	 * (non-Javadoc)
440
	 *
441
	 * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteGroup(java.lang.Long,
442
	 *      java.lang.Long)
443
	 */
444
	public void deleteGroup(final Long userId, final Long groupId) throws ObjectNotFoundException, InsufficientPermissionsException {
445
		// Validate.
446
		if (userId == null)
447
			throw new ObjectNotFoundException("No user specified");
448
		if (groupId == null)
449
			throw new ObjectNotFoundException("No group specified");
450

  
451
		// Do the actual work.
452
		final User owner = dao.getEntityById(User.class, userId);
453
		final Group group = dao.getEntityById(Group.class, groupId);
454
		// Only delete the group if actually owned by the user.
455
		if (group.getOwner().equals(owner)) {
456
			List<Folder> folders = dao.getFoldersPermittedForGroup(userId, groupId);
457
			for (Folder f : folders){
458
				f.getPermissions().removeAll(group.getPermissions());
459
				for(FileHeader file : f.getFiles())
460
					file.getPermissions().removeAll(group.getPermissions());
461
			}
462
			List<FileHeader> files = dao.getSharedFilesNotInSharedFolders(userId);
463
			for(FileHeader h : files)
464
				h.getPermissions().removeAll(group.getPermissions());
465
			owner.removeSpecifiedGroup(group);
466
			dao.delete(group);
467
		}
468
		else throw new InsufficientPermissionsException("You are not the owner of this group");
469
	}
470

  
471
	@Override
472
	public FileHeaderDTO createFile(Long userId, Long folderId, String name, String mimeType, InputStream stream)
473
			throws DuplicateNameException, ObjectNotFoundException, GSSIOException,
474
			InsufficientPermissionsException, QuotaExceededException {
475
		File file = null;
476
		try {
477
			file = uploadFile(stream, userId);
478
		} catch ( IOException ioe) {
479
			// Supply a more accurate problem description.
480
			throw new GSSIOException("Problem creating file",ioe);
481
		}
482
		return createFile(userId, folderId, name, mimeType, file);
483
	}
484

  
485
	/* (non-Javadoc)
486
	 * @see gr.ebs.gss.server.ejb.ExternalAPIRemote#indexFile(java.lang.Long, boolean)
487
	 */
488
	public void indexFile(Long fileId, boolean delete) {
489
		Connection qConn = null;
490
		Session session = null;
491
		MessageProducer sender = null;
492
		try {
493
			Context jndiCtx = new InitialContext();
494
			ConnectionFactory factory = (QueueConnectionFactory) jndiCtx.lookup("java:/JmsXA");
495
			Queue queue = (Queue) jndiCtx.lookup("queue/gss-indexingQueue");
496
			qConn = factory.createConnection();
497
			session = qConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
498
			sender = session.createProducer(queue);
499

  
500
			MapMessage map = session.createMapMessage();
501
			map.setObject("id", fileId);
502
			map.setBoolean("delete", delete);
503
			sender.send(map);
504
		}
505
		catch (NamingException e) {
506
			logger.error("Index was not updated: ", e);
507
		}
508
		catch (JMSException e) {
509
			logger.error("Index was not updated: ", e);
510
		}
511
		finally {
512
			try {
513
				if (sender != null)
514
					sender.close();
515
				if (session != null)
516
					session.close();
517
				if (qConn != null)
518
					qConn.close();
519
			}
520
			catch (JMSException e) {
521
				logger.warn(e);
522
			}
523
		}
524
	}
525

  
526

  
527

  
528
	/**
529
	 * A helper method that generates a unique file path for a stored file. The
530
	 * files are stored using random hash names that are distributed evenly in
531
	 * a 2-level tree of subdirectories named after the first two hex characters
532
	 * in the name. For example, file ab1234cd5769f will be stored in the path
533
	 * /file-repository-root/a/b/ab1234cd5769f. The directories will be created
534
	 * if they don't already exist.
535
	 *
536
	 * @return a unique new file path
537
	 */
538
	private String generateRepositoryFilePath() {
539
		String filename = Long.toHexString(random.nextLong());
540
		String fileRepositoryPath = getConfiguration().getString("fileRepositoryPath","/tmp");
541
		File root = new File(fileRepositoryPath);
542
		if (!root.exists())
543
			root.mkdirs();
544
		File firstFolder = new File(root + File.separator + filename.substring(0, 1));
545
		if (!firstFolder.exists())
546
			firstFolder.mkdir();
547
		File secondFolder = new File(firstFolder + File.separator + filename.substring(1, 2));
548
		if (!secondFolder.exists())
549
			secondFolder.mkdir();
550
		return secondFolder + File.separator + filename;
551
	}
552

  
553
	/*
554
	 * (non-Javadoc)
555
	 *
556
	 * @see gr.ebs.gss.server.ejb.ExternalAPI#deleteFile(java.lang.Long,
557
	 *      java.lang.Long)
558
	 */
559
	public void deleteFile(final Long userId, final Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
560
		// Validate.
561
		if (userId == null)
562
			throw new ObjectNotFoundException("No user specified");
563
		if (fileId == null)
564
			throw new ObjectNotFoundException("No file specified");
565

  
566
		// Do the actual work.
567
		final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
568
		final Folder parent = file.getFolder();
569
		if (parent == null)
570
			throw new ObjectNotFoundException("The specified file has no parent folder");
571
		final User user = dao.getEntityById(User.class, userId);
572
		if (!file.hasDeletePermission(user))
573
			throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
574
		for (final FileBody body : file.getBodies()) {
575
			final File fileContents = new File(body.getStoredFilePath());
576
			if (!fileContents.delete())
577
				logger.error("Could not delete file " + body.getStoredFilePath());
578
		}
579
		dao.delete(file);
580
		indexFile(fileId, true);
581
	}
582

  
583
	/*
584
	 * (non-Javadoc)
585
	 *
586
	 * @see gr.ebs.gss.server.ejb.ExternalAPI#createTag(java.lang.Long,
587
	 *      java.lang.Long, java.lang.String)
588
	 */
589
	public void createTag(final Long userId, final Long fileHeaderId, final String tag) throws ObjectNotFoundException {
590
		if (userId == null)
591
			throw new ObjectNotFoundException("No user specified");
592
		if (fileHeaderId == null)
593
			throw new ObjectNotFoundException("No file specified");
594
		if (StringUtils.isEmpty(tag))
595
			throw new ObjectNotFoundException("Tag is empty");
596

  
597
		final User user = dao.getEntityById(User.class, userId);
598
		final FileHeader fh = dao.getEntityById(FileHeader.class, fileHeaderId);
599
		user.addTag(fh, tag);
600
	}
601

  
602
	/* (non-Javadoc)
603
	 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUserTags(java.lang.Long)
604
	 */
605
	@WebMethod(operationName = "getUserTags")
606
	public Set<String> getUserTags(final Long userId) throws ObjectNotFoundException {
607
		return dao.getUserTags(userId);
608
	}
609

  
610
	/* (non-Javadoc)
611
	 * @see gr.ebs.gss.server.ejb.ExternalAPI#updateFile(java.lang.Long, java.lang.Long, java.lang.String, java.util.Set)
612
	 */
613
	public void updateFile(Long userId, Long fileId, String name, String tagSet) throws ObjectNotFoundException, InsufficientPermissionsException {
614
		if (userId == null)
615
			throw new ObjectNotFoundException("No user specified");
616
		if (fileId == null)
617
			throw new ObjectNotFoundException("No file specified");
618
		FileHeader file = dao.getEntityById(FileHeader.class, fileId);
619
		User user = dao.getEntityById(User.class, userId);
620
		if (!file.hasWritePermission(user))
621
			throw new InsufficientPermissionsException("User " + user.getId() + " cannot update file " + file.getName() + "(" + file.getId() + ")");
622

  
623
		if (name != null)
624
			file.setName(name);
625
		List<FileTag> tags = file.getFileTags();
626

  
627
		if (tagSet != null) {
628
			Iterator<FileTag> i = tags.iterator();
629
			while (i.hasNext()) {
630
				FileTag tag = i.next();
631
				i.remove();
632
				tag.setFile(null);
633
				user.removeTag(tag);
634
				dao.delete(tag);
635
			}
636
			dao.flush();
637
			StringTokenizer st = new StringTokenizer(tagSet, ",");
638
			while (st.hasMoreTokens())
639
				new FileTag(user, file, st.nextToken().trim());
640
		}
641

  
642
		// Re-index the file if it was modified.
643
		if (name != null || tagSet != null)
644
			indexFile(fileId, false);
645
	}
646

  
647
	@Override
648
	public InputStream getFileContents(Long userId, Long fileId)
649
			throws ObjectNotFoundException, InsufficientPermissionsException {
650
		if (userId == null)
651
			throw new ObjectNotFoundException("No user specified");
652
		if (fileId == null)
653
			throw new ObjectNotFoundException("No file specified");
654

  
655
		FileHeader header = dao.getEntityById(FileHeader.class, fileId);
656
		User user = dao.getEntityById(User.class, userId);
657
		if (!header.hasReadPermission(user)) {
658
			logger.info("User " + user.getId() + " cannot read file " + header.getName() + "(" + fileId + ")");
659
			throw new InsufficientPermissionsException("You don't have the necessary permissions");
660
		}
661

  
662
		File f = new File(header.getCurrentBody().getStoredFilePath());
663
		try {
664
			return new FileInputStream(f);
665
		} catch (FileNotFoundException e) {
666
			logger.error("Could not locate the contents of file " + f.getAbsolutePath());
667
			throw new ObjectNotFoundException("The file contents could not be located");
668
		}
669
	}
670

  
671
	/* (non-Javadoc)
672
	 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFileContents(java.lang.Long, java.lang.Long, java.lang.Long)
673
	 */
674
	public InputStream getFileContents(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
675
		if (userId == null)
676
			throw new ObjectNotFoundException("No user specified");
677
		if (fileId == null)
678
			throw new ObjectNotFoundException("No file specified");
679
		if (bodyId == null)
680
			throw new ObjectNotFoundException("No file specified");
681

  
682
		final FileHeader header = dao.getEntityById(FileHeader.class, fileId);
683
		final FileBody body = dao.getEntityById(FileBody.class, bodyId);
684
		final User user = dao.getEntityById(User.class, userId);
685
		if (!header.hasReadPermission(user)) {
686
			logger.info("User " + user.getId() + " cannot read file " + header.getName() + "(" + fileId + ")");
687
			throw new InsufficientPermissionsException("You don't have the necessary permissions");
688
		}
689

  
690
		File f = new File(body.getStoredFilePath());
691
		try {
692
			return new FileInputStream(f);
693
		} catch (FileNotFoundException e) {
694
			logger.error("Could not locate the contents of file " + f.getAbsolutePath());
695
			throw new ObjectNotFoundException("The file contents could not be located");
696
		}
697
	}
698

  
699
	/* (non-Javadoc)
700
	 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFile(java.lang.Long, java.lang.Long)
701
	 */
702
	public FileHeaderDTO getFile(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
703
		if (userId == null)
704
			throw new ObjectNotFoundException("No user specified");
705
		if (fileId == null)
706
			throw new ObjectNotFoundException("No file specified");
707
		final User user = dao.getEntityById(User.class, userId);
708
		final FileHeader file = dao.getEntityById(FileHeader.class, fileId);
709
		if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
710
			throw new InsufficientPermissionsException("You don't have the necessary permissions");
711
		return file.getDTO();
712
	}
713

  
714
	@Override
715
	public FileBodyDTO getFileBody(Long userId, Long fileId, Long bodyId) throws ObjectNotFoundException, InsufficientPermissionsException {
716
		if (userId == null)
717
			throw new ObjectNotFoundException("No user specified");
718
		if (fileId == null)
719
			throw new ObjectNotFoundException("No file specified");
720
		User user = dao.getEntityById(User.class, userId);
721
		FileHeader file = dao.getEntityById(FileHeader.class, fileId);
722
		if (!file.hasReadPermission(user) && !file.getFolder().hasReadPermission(user))
723
			throw new InsufficientPermissionsException("You don't have the necessary permissions");
724
		FileBody body = dao.getEntityById(FileBody.class, bodyId);
725
		return body.getDTO();
726
	}
727

  
728
	@Override
729
	public Object getResourceAtPath(Long ownerId, String path, boolean ignoreDeleted)
730
			throws ObjectNotFoundException {
731
		if (ownerId == null)
732
			throw new ObjectNotFoundException("No user specified");
733
		if (StringUtils.isEmpty(path))
734
			throw new ObjectNotFoundException("No path specified");
735

  
736
		User owner = dao.getEntityById(User.class, ownerId);
737
		List<String> pathElements = new ArrayList<String>();
738
		StringTokenizer st = new StringTokenizer(path, "/");
739
		while (st.hasMoreTokens())
740
			pathElements.add(st.nextToken());
741
		if (pathElements.size() < 1)
742
			return getRootFolder(owner.getId());
743
		// Store the last element, since it requires special handling.
744
		String lastElement = pathElements.remove(pathElements.size() - 1);
745
		FolderDTO cursor = getRootFolder(owner.getId());
746
		// Traverse and verify the specified folder path.
747
		for (String pathElement : pathElements) {
748
			cursor = getFolder(cursor.getId(), pathElement);
749
			if (cursor.isDeleted())
750
				throw new ObjectNotFoundException("Folder " + cursor.getPath() + " not found");
751
		}
752

  
753
		// Use the lastElement to retrieve the actual resource.
754
		Object resource = null;
755
		try {
756
			FileHeaderDTO file = getFile(cursor.getId(), lastElement);
757
			if (ignoreDeleted && file.isDeleted())
758
				throw new ObjectNotFoundException("Resource not found");
759
			resource = file;
760
		} catch (ObjectNotFoundException e) {
761
			// Perhaps the requested resource is not a file, so
762
			// check for folders as well.
763
			FolderDTO folder = getFolder(cursor.getId(), lastElement);
764
			if (ignoreDeleted && folder.isDeleted())
765
				throw new ObjectNotFoundException("Resource not found");
766
			resource = folder;
767
		}
768
		return resource;
769
	}
770

  
771
	/**
772
	 * Retrieve a file for the specified user that has the specified name and
773
	 * its parent folder has id equal to folderId.
774
	 *
775
	 * @param userId the ID of the current user
776
	 * @param folderId the ID of the parent folder
777
	 * @param name the name of the requested file
778
	 * @return the file found
779
	 * @throws ObjectNotFoundException if the specified folder or file was not
780
	 *             found, with the exception message mentioning the precise
781
	 *             problem
782
	 */
783
	private FileHeaderDTO getFile(Long folderId, String name) throws ObjectNotFoundException {
784
		if (folderId == null)
785
			throw new ObjectNotFoundException("No parent folder specified");
786
		if (StringUtils.isEmpty(name))
787
			throw new ObjectNotFoundException("No file specified");
788

  
789
		FileHeader file = dao.getFile(folderId, name);
790
		return file.getDTO();
791
	}
792

  
793
	/**
794
	 * Retrieve a folder for the specified user that has the specified name and
795
	 * its parent folder has id equal to parentId.
796
	 *
797
	 * @param parentId the ID of the parent folder
798
	 * @param name the name of the requested folder
799
	 * @return the folder found
800
	 * @throws ObjectNotFoundException if the specified folder or parent was not
801
	 *             found, with the exception message mentioning the precise
802
	 *             problem
803
	 */
804
	private FolderDTO getFolder(Long parentId, String name) throws ObjectNotFoundException {
805
		if (parentId == null)
806
			throw new ObjectNotFoundException("No parent folder specified");
807
		if (StringUtils.isEmpty(name))
808
			throw new ObjectNotFoundException("No folder specified");
809

  
810
		Folder folder = dao.getFolder(parentId, name);
811
		return folder.getDTO();
812
	}
813

  
814
	private FileHeaderDTO updateFileContents(Long userId, Long fileId, String mimeType, InputStream resourceInputStream) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
815
		File file = null;
816
		try {
817
			file = uploadFile(resourceInputStream, userId);
818
		} catch ( IOException ioe) {
819
			// Supply a more accurate problem description.
820
			throw new GSSIOException("Problem creating file",ioe);
821
		}
822
		return updateFileContents(userId, fileId, mimeType, file);
823
	}
824

  
825
	@Override
826
	public void copyFile(Long userId, Long fileId, String dest) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
827
		if (userId == null)
828
			throw new ObjectNotFoundException("No user specified");
829
		if (fileId == null)
830
			throw new ObjectNotFoundException("No file specified");
831
		if (StringUtils.isEmpty(dest))
832
			throw new ObjectNotFoundException("No destination specified");
833

  
834
		Object destination = getResourceAtPath(userId, getParentPath(dest), true);
835
		if (!(destination instanceof FolderDTO))
836
			throw new ObjectNotFoundException("Destination parent folder not found");
837
		FolderDTO parent = (FolderDTO) destination;
838
		copyFile(userId, fileId, parent.getId(), getLastElement(dest));
839
	}
840

  
841
	@Override
842
	public void copyFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
843
		if (userId == null)
844
			throw new ObjectNotFoundException("No user specified");
845
		if (ownerId == null)
846
			throw new ObjectNotFoundException("No owner specified");
847
		if (fileId == null)
848
			throw new ObjectNotFoundException("No file specified");
849
		if (StringUtils.isEmpty(dest))
850
			throw new ObjectNotFoundException("No destination specified");
851

  
852
		Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
853
		if (!(destination instanceof FolderDTO))
854
			throw new ObjectNotFoundException("Destination parent folder not found");
855
		FolderDTO parent = (FolderDTO) destination;
856
		copyFile(userId, fileId, parent.getId(), getLastElement(dest));
857
	}
858

  
859
	@Override
860
	public void copyFile(Long userId, Long fileId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
861
		if (userId == null)
862
			throw new ObjectNotFoundException("No user specified");
863
		if (fileId == null)
864
			throw new ObjectNotFoundException("No file specified");
865
		if (destId == null)
866
			throw new ObjectNotFoundException("No destination specified");
867
		if (StringUtils.isEmpty(destName))
868
			throw new ObjectNotFoundException("No destination file name specified");
869

  
870
		FileHeader file = dao.getEntityById(FileHeader.class, fileId);
871
		Folder destination = dao.getEntityById(Folder.class, destId);
872
		User user = dao.getEntityById(User.class, userId);
873
		if (!file.hasReadPermission(user) || !destination.hasWritePermission(user))
874
			throw new InsufficientPermissionsException("You don't have the necessary permissions");
875
		int versionsNumber = file.getBodies().size();
876
		FileBody oldestBody = file.getBodies().get(0);
877
		assert oldestBody != null;
878
		File contents = new File(oldestBody.getStoredFilePath());
879
		try {
880
			createFile(user.getId(), destination.getId(), destName, oldestBody.getMimeType(), new FileInputStream(contents));
881
			FileHeader copiedFile = dao.getFile(destination.getId(), destName);
882
			dao.flush();
883
			if (versionsNumber > 1)
884
				for (int i = 1; i < versionsNumber; i++) {
885
					FileBody body = file.getBodies().get(i);
886
					assert body != null;
887
					contents = new File(body.getStoredFilePath());
888
					updateFileContents(user.getId(), copiedFile.getId(), body.getMimeType(), new FileInputStream(contents));
889
				}
890
			List<FileTag> tags = file.getFileTags();
891
			for (FileTag tag : tags)
892
				createTag(userId, copiedFile.getId(), tag.getTag());
893

  
894
		} catch (FileNotFoundException e) {
895
			throw new ObjectNotFoundException("File contents not found for file " + contents.getAbsolutePath());
896
		}
897

  
898
	}
899

  
900
	@Override
901
	public void copyFolder(Long userId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
902
		if (userId == null)
903
			throw new ObjectNotFoundException("No user specified");
904
		if (folderId == null)
905
			throw new ObjectNotFoundException("No folder specified");
906
		if (StringUtils.isEmpty(dest))
907
			throw new ObjectNotFoundException("No destination specified");
908

  
909
		Object destination = getResourceAtPath(userId, getParentPath(dest), true);
910
		if (!(destination instanceof FolderDTO))
911
			throw new ObjectNotFoundException("Destination folder not found");
912
		FolderDTO parent = (FolderDTO) destination;
913
		copyFolder(userId, folderId, parent.getId(), getLastElement(dest));
914
	}
915

  
916
	@Override
917
	public void copyFolder(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
918
		if (userId == null)
919
			throw new ObjectNotFoundException("No user specified");
920
		if (folderId == null)
921
			throw new ObjectNotFoundException("No folder specified");
922
		if (destId == null)
923
			throw new ObjectNotFoundException("No destination specified");
924
		if (StringUtils.isEmpty(destName))
925
			throw new ObjectNotFoundException("No destination folder name specified");
926
		Folder folder = dao.getEntityById(Folder.class, folderId);
927
		Folder destination = dao.getEntityById(Folder.class, destId);
928
		User user = dao.getEntityById(User.class, userId);
929
		if (!destination.hasWritePermission(user) || !folder.hasReadPermission(user))
930
			throw new InsufficientPermissionsException("You don't have the necessary permissions");
931
		createFolder(user.getId(), destination.getId(), destName);
932
	}
933

  
934
	@Override
935
	public void copyFolderStructureToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
936
		if (userId == null)
937
			throw new ObjectNotFoundException("No user specified");
938
		if (ownerId == null)
939
			throw new ObjectNotFoundException("No owner specified");
940
		if (folderId == null)
941
			throw new ObjectNotFoundException("No folder specified");
942
		if (StringUtils.isEmpty(dest))
943
			throw new ObjectNotFoundException("No destination specified");
944

  
945
		Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
946
		if (!(destination instanceof FolderDTO))
947
			throw new ObjectNotFoundException("Destination folder not found");
948
		FolderDTO parent = (FolderDTO) destination;
949
		copyFolderStructure(userId, folderId, parent.getId(), getLastElement(dest));
950
	}
951

  
952
	@Override
953
	public void copyFolderStructure(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
954
		if (userId == null)
955
			throw new ObjectNotFoundException("No user specified");
956
		if (folderId == null)
957
			throw new ObjectNotFoundException("No folder specified");
958
		if (destId == null)
959
			throw new ObjectNotFoundException("No destination specified");
960
		if (StringUtils.isEmpty(destName))
961
			throw new ObjectNotFoundException("No destination folder name specified");
962

  
963
		Folder folder = dao.getEntityById(Folder.class, folderId);
964
		Folder destination = dao.getEntityById(Folder.class, destId);
965
		final User user = dao.getEntityById(User.class, userId);
966
		// XXX: quick fix need to copy only visible items to user (Source
967
		// for bugs)
968
		if (!folder.getOwner().getId().equals(userId) && !folder.hasReadPermission(user))
969
			return;
970
		if(folder.isDeleted())//do not copy trashed folder and contents
971
			return;
972
		if (!destination.hasWritePermission(user) || !folder.hasReadPermission(user))
973
			throw new InsufficientPermissionsException("You don't have the necessary permissions");
974
		createFolder(user.getId(), destination.getId(), destName);
975
		Folder createdFolder = dao.getFolder(destination.getId(), destName);
976
		List<FileHeader> files = folder.getFiles();
977
		if (files != null)
978
			for (FileHeader file : files)
979
				if(!file.isDeleted())
980
					copyFile(userId, file.getId(), createdFolder.getId(), file.getName());
981
		List<Folder> subFolders = folder.getSubfolders();
982
		if (subFolders != null)
983
			for (Folder sub : subFolders)
984
				if(!sub.getId().equals(createdFolder.getId()))
985
					copyFolderStructure(userId, sub.getId(), createdFolder.getId(), sub.getName());
986

  
987
	}
988

  
989
	/**
990
	 * For a provided path, remove the last element and return the rest, that is
991
	 * the path of the parent folder.
992
	 *
993
	 * @param path the specified path
994
	 * @return the path of the parent folder
995
	 * @throws ObjectNotFoundException if the provided string contains no path
996
	 *             delimiters
997
	 */
998
	private String getParentPath(String path) throws ObjectNotFoundException {
999
		int lastDelimiter = path.lastIndexOf('/');
1000
		if (lastDelimiter == 0)
1001
			return "/";
1002
		if (lastDelimiter == -1)
1003
			// No path found.
1004
			throw new ObjectNotFoundException("There is no parent in the path: " + path);
1005
		else if (lastDelimiter < path.length() - 1)
1006
			// Return the part before the delimiter.
1007
			return path.substring(0, lastDelimiter);
1008
		else {
1009
			// Remove the trailing delimiter and then recurse.
1010
			String strippedTrail = path.substring(0, lastDelimiter);
1011
			return getParentPath(strippedTrail);
1012
		}
1013
	}
1014

  
1015
	/**
1016
	 * Get the last element in a path that denotes the file or folder name.
1017
	 *
1018
	 * @param path the provided path
1019
	 * @return the last element in the path
1020
	 */
1021
	private String getLastElement(String path) {
1022
		int lastDelimiter = path.lastIndexOf('/');
1023
		if (lastDelimiter == -1)
1024
			// No path found.
1025
			return path;
1026
		else if (lastDelimiter < path.length() - 1)
1027
			// Return the part after the delimiter.
1028
			return path.substring(lastDelimiter + 1);
1029
		else {
1030
			// Remove the trailing delimiter and then recurse.
1031
			String strippedTrail = path.substring(0, lastDelimiter);
1032
			return getLastElement(strippedTrail);
1033
		}
1034
	}
1035

  
1036
	@Override
1037
	public void moveFileToTrash(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
1038
		if (userId == null)
1039
			throw new ObjectNotFoundException("No user specified");
1040
		if (fileId == null)
1041
			throw new ObjectNotFoundException("No file specified");
1042

  
1043
		// Do the actual work.
1044
		FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1045
		Folder parent = file.getFolder();
1046
		if (parent == null)
1047
			throw new ObjectNotFoundException("The specified file has no parent folder");
1048
		User user = dao.getEntityById(User.class, userId);
1049
		if (!file.hasDeletePermission(user))
1050
			throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
1051

  
1052
		file.setDeleted(true);
1053
		dao.update(file);
1054
	}
1055

  
1056
	@Override
1057
	public void moveFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, InsufficientPermissionsException, DuplicateNameException, GSSIOException, QuotaExceededException {
1058
		if (userId == null)
1059
			throw new ObjectNotFoundException("No user specified");
1060
		if (ownerId == null)
1061
			throw new ObjectNotFoundException("No owner specified");
1062
		if (fileId == null)
1063
			throw new ObjectNotFoundException("No file specified");
1064
		if (StringUtils.isEmpty(dest))
1065
			throw new ObjectNotFoundException("No destination specified");
1066

  
1067
		Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1068
		if (!(destination instanceof FolderDTO))
1069
			throw new ObjectNotFoundException("Destination parent folder not found");
1070
		FolderDTO parent = (FolderDTO) destination;
1071
		moveFile(userId, fileId, parent.getId(), getLastElement(dest));
1072
	}
1073

  
1074
	@Override
1075
	public void moveFile(Long userId, Long fileId, Long destId, String destName) throws InsufficientPermissionsException, ObjectNotFoundException, DuplicateNameException, GSSIOException, QuotaExceededException {
1076
		if (userId == null)
1077
			throw new ObjectNotFoundException("No user specified");
1078
		if (fileId == null)
1079
			throw new ObjectNotFoundException("No file specified");
1080
		if (destId == null)
1081
			throw new ObjectNotFoundException("No destination specified");
1082
		if (StringUtils.isEmpty(destName))
1083
			throw new ObjectNotFoundException("No destination file name specified");
1084

  
1085
		FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1086
		Folder destination = dao.getEntityById(Folder.class, destId);
1087

  
1088
		User owner = dao.getEntityById(User.class, userId);
1089
		if (!file.hasDeletePermission(owner) || !destination.hasWritePermission(owner))
1090
			throw new InsufficientPermissionsException("User " + owner.getId() + " cannot move file " + file.getName() + "(" + file.getId() + ")");
1091
		FileBody body = file.getCurrentBody();
1092
		assert body != null;
1093
		File contents = new File(body.getStoredFilePath());
1094
		try {
1095
			createFile(owner.getId(), destination.getId(), destName, body.getMimeType(), new FileInputStream(contents));
1096
		} catch (FileNotFoundException e) {
1097
			throw new ObjectNotFoundException("File contents not found for file " + body.getStoredFilePath());
1098
		}
1099
		deleteFile(userId, fileId);
1100

  
1101
	}
1102

  
1103
	@Override
1104
	public void moveFolderToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1105
		if (userId == null)
1106
			throw new ObjectNotFoundException("No user specified");
1107
		if (ownerId == null)
1108
			throw new ObjectNotFoundException("No owner specified");
1109
		if (folderId == null)
1110
			throw new ObjectNotFoundException("No folder specified");
1111
		if (StringUtils.isEmpty(dest))
1112
			throw new ObjectNotFoundException("No destination specified");
1113

  
1114
		Object destination = getResourceAtPath(ownerId, getParentPath(dest), true);
1115
		if (!(destination instanceof FolderDTO))
1116
			throw new ObjectNotFoundException("Destination parent folder not found");
1117
		FolderDTO parent = (FolderDTO) destination;
1118
		moveFolder(userId, folderId, parent.getId(), getLastElement(dest));
1119
	}
1120

  
1121
	@Override
1122
	public void moveFolder(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException {
1123
		// TODO Simple Move and delete of original folder, in production
1124
		// scenario we must first check individual files and folders permissions
1125
		copyFolderStructure(userId, folderId, destId, destName);
1126
		deleteFolder(userId, folderId);
1127
	}
1128

  
1129
	/* (non-Javadoc)
1130
	 * @see gr.ebs.gss.server.ejb.ExternalAPI#getDeletedFiles(java.lang.Long)
1131
	 */
1132
	public List<FileHeaderDTO> getDeletedFiles(Long userId) throws ObjectNotFoundException {
1133
		// Validate.
1134
		if (userId == null)
1135
			throw new ObjectNotFoundException("No user specified");
1136

  
1137
		// Do the actual work.
1138
		final List<FileHeaderDTO> result = new ArrayList<FileHeaderDTO>();
1139
		final List<FileHeader> files = dao.getDeletedFiles(userId);
1140
		for (final FileHeader f : files)
1141
			result.add(f.getDTO());
1142
		return result;
1143
	}
1144

  
1145
	@Override
1146
	public void removeFileFromTrash(Long userId, Long fileId)
1147
			throws ObjectNotFoundException, InsufficientPermissionsException {
1148
		if (userId == null)
1149
			throw new ObjectNotFoundException("No user specified");
1150
		if (fileId == null)
1151
			throw new ObjectNotFoundException("No file specified");
1152

  
1153
		// Do the actual work.
1154
		FileHeader file = dao.getEntityById(FileHeader.class, fileId);
1155
		Folder parent = file.getFolder();
1156
		if (parent == null)
1157
			throw new ObjectNotFoundException("The specified file has no parent folder");
1158
		User user = dao.getEntityById(User.class, userId);
1159
		if (!file.hasDeletePermission(user))
1160
			throw new InsufficientPermissionsException("User " + user.getUsername() +
1161
						" cannot restore file " + file.getName());
1162

  
1163
		file.setDeleted(false);
1164
		dao.update(file);
1165
	}
1166

  
1167
	@Override
1168
	public void moveFolderToTrash(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
1169
		if (userId == null)
1170
			throw new ObjectNotFoundException("No user specified");
1171
		if (folderId == null)
1172
			throw new ObjectNotFoundException("No folder specified");
1173
		Folder folder = dao.getEntityById(Folder.class, folderId);
1174
		User user = dao.getEntityById(User.class, userId);
1175
		if (!folder.hasDeletePermission(user))
1176
			throw new InsufficientPermissionsException("You don't have the necessary permissions");
1177
		folder.setDeleted(true);
1178
		dao.update(folder);
1179
		for (FileHeader file : folder.getFiles())
1180
			moveFileToTrash(userId, file.getId());
1181
		for (Folder subFolder : folder.getSubfolders())
1182
			moveFolderToTrash(userId, subFolder.getId());
1183

  
1184
	}
1185

  
1186
	@Override
1187
	public void removeFolderFromTrash(Long userId, Long folderId)
1188
			throws ObjectNotFoundException, InsufficientPermissionsException {
1189
		if (userId == null)
1190
			throw new ObjectNotFoundException("No user specified");
1191
		if (folderId == null)
1192
			throw new ObjectNotFoundException("No folder specified");
1193
		Folder folder = dao.getEntityById(Folder.class, folderId);
1194
		User user = dao.getEntityById(User.class, userId);
1195
		if (!folder.hasDeletePermission(user))
1196
			throw new InsufficientPermissionsException("User " + user.getUsername() +
1197
						" cannot restore folder " + folder.getName());
1198
		folder.setDeleted(false);
1199
		for (FileHeader file : folder.getFiles())
1200
			removeFileFromTrash(userId, file.getId());
1201
		for (Folder subFolder : folder.getSubfolders())
1202
			removeFolderFromTrash(userId, subFolder.getId());
1203
		dao.update(folder);
1204
	}
1205

  
1206
	@Override
1207
	public List<FolderDTO> getDeletedRootFolders(Long userId) throws ObjectNotFoundException {
1208
		List<Folder> folders = dao.getDeletedRootFolders(userId);
1209
		List<FolderDTO> result = new ArrayList<FolderDTO>();
1210
		for (Folder folder : folders)
1211
			result.add(folder.getDTO());
1212
		return result;
1213
	}
1214

  
1215
	@Override
1216
	public void emptyTrash(Long userId) throws ObjectNotFoundException, InsufficientPermissionsException {
1217
		List<FolderDTO> deletedRootFolders = getDeletedRootFolders(userId);
1218
		for (FolderDTO fdto : deletedRootFolders)
1219
			deleteFolder(userId, fdto.getId());
1220
		List<FileHeaderDTO> deletedFiles = getDeletedFiles(userId);
1221
		for (FileHeaderDTO filedto : deletedFiles)
1222
			deleteFile(userId, filedto.getId());
1223
	}
1224

  
1225
	@Override
1226
	public void restoreTrash(Long userId) throws ObjectNotFoundException, InsufficientPermissionsException {
1227
		List<FolderDTO> deletedRootFolders = getDeletedRootFolders(userId);
1228
		for (FolderDTO fdto : deletedRootFolders)
1229
			removeFolderFromTrash(userId, fdto.getId());
1230
		List<FileHeaderDTO> deletedFiles = getDeletedFiles(userId);
1231
		for (FileHeaderDTO filedto : deletedFiles)
1232
			removeFileFromTrash(userId, filedto.getId());
1233
	}
1234

  
1235
	@Override
1236
	public User createUser(String username, String name, String mail) throws ObjectNotFoundException {
1237
		if (username == null)
1238
			throw new ObjectNotFoundException("No username specified");
1239
		if (name == null)
1240
			throw new ObjectNotFoundException("No name specified");
1241

  
1242
		User user = new User();
1243
		user.setUsername(username);
1244
		user.setName(name);
1245
		user.setEmail(mail);
1246
		Date now = new Date();
1247
		AuditInfo auditInfo = new AuditInfo();
1248
		auditInfo.setCreationDate(now);
1249
		auditInfo.setModificationDate(now);
1250
		user.setAuditInfo(auditInfo);
1251
		user.generateAuthToken();
1252
		dao.create(user);
1253
		// Make sure we get an ID in the user object.
1254
		dao.flush();
1255
		// Create the root folder for the user.
1256
		createFolder(user.getName(), null, user);
1257
		return user;
1258
	}
1259

  
1260
	@Override
1261
	public User findUserByEmail(String email) {
1262
		return dao.findUserByEmail(email);
1263
	}
1264

  
1265
	@Override
1266
	public void updateUser(User user) {
1267
		dao.update(user);
1268
	}
1269

  
1270
	@Override
1271
	public User updateUser(String username, String name, String mail) throws ObjectNotFoundException {
1272
		if (username == null)
1273
			throw new ObjectNotFoundException("No username specified");
1274

  
1275
		User user = dao.getUser(username);
1276
		user.setName(name);
1277
		user.setEmail(mail);
1278
		return user;
1279
	}
1280

  
1281
	@Override
1282
	public User findUser(String username) {
1283
		if (username == null)
1284
			return null;
1285
		return dao.findUser(username);
1286
	}
1287

  
1288
	@Override
1289
	public User updateUserToken(Long userId) throws ObjectNotFoundException {
1290
		if (userId == null)
1291
			throw new ObjectNotFoundException("No user specified");
1292
		User user = dao.getEntityById(User.class, userId);
1293
		user.generateAuthToken();
1294
		return user;
1295
	}
1296

  
1297
	/* (non-Javadoc)
1298
	 * @see gr.ebs.gss.server.ejb.ExternalAPI#getFolderPermissions(java.lang.Long, java.lang.Long)
1299
	 */
1300
	@Override
1301
	public Set<PermissionDTO> getFolderPermissions(Long userId, Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException {
1302
		if (userId == null)
1303
			throw new ObjectNotFoundException("No user specified");
1304
		if (folderId == null)
1305
			throw new ObjectNotFoundException("No folder specified");
1306
		User user = dao.getEntityById(User.class, userId);
1307
		Folder folder = dao.getEntityById(Folder.class, folderId);
1308
		if(!folder.hasReadPermission(user))
1309
			throw new InsufficientPermissionsException("You don't have the necessary permissions");
1310
		Set<Permission> perms = folder.getPermissions();
1311
		Set<PermissionDTO> result = new LinkedHashSet<PermissionDTO>();
1312
		for (Permission perm : perms)
1313
			if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId()))
1314
				result.add(perm.getDTO());
1315
		for (Permission perm : perms)
1316
			if (perm.getUser() != null && perm.getUser().getId().equals(folder.getOwner().getId())) {
1317
			} else
1318
				result.add(perm.getDTO());
1319
		return result;
1320

  
1321
	}
1322

  
1323
	/* (non-Javadoc)
1324
	 * @see gr.ebs.gss.server.ejb.ExternalAPI#setFolderPermissions(java.lang.Long, java.lang.Long, java.util.Set)
1325
	 */
1326
	@Override
1327
	public void setFolderPermissions(Long userId, Long folderId, Set<PermissionDTO> permissions) throws ObjectNotFoundException, InsufficientPermissionsException {
1328
		if (userId == null)
1329
			throw new ObjectNotFoundException("No user specified");
1330
		if (folderId == null)
1331
			throw new ObjectNotFoundException("No folder specified");
1332
		User user = dao.getEntityById(User.class, userId);
1333
		Folder folder = dao.getEntityById(Folder.class, folderId);
1334
		if(!folder.hasModifyACLPermission(user))
1335
			throw new InsufficientPermissionsException("You don't have the necessary permissions");
1336
		folder.getPermissions().clear();
1337
		for (PermissionDTO dto : permissions) {
1338
			if (dto.getUser()!=null && dto.getUser().getId().equals(folder.getOwner().getId()) && (!dto.hasRead() || !dto.hasWrite() || !dto.hasModifyACL()))
1339
					throw new InsufficientPermissionsException("Can't remove permissions from owner");
1340
			folder.addPermission(getPermission(dto));
1341
		}
1342
		dao.update(folder);
1343
		for (FileHeader fh : folder.getFiles())
1344
			setFilePermissions(userId, fh.getId(), fh.isReadForAll(), permissions);
1345
		for (Folder sub : folder.getSubfolders())
1346
			setFolderPermissions(userId, sub.getId(), permissions);
1347
	}
1348

  
1349
	private Permission getPermission(PermissionDTO dto) throws ObjectNotFoundException {
1350
		Permission res = new Permission();
1351
		if (dto.getGroup() != null)
1352
			res.setGroup(dao.getEntityById(Group.class, dto.getGroup().getId()));
1353
		else if (dto.getUser() != null)
1354
			if (dto.getUser().getId() == null)
1355
				res.setUser(dao.getUser(dto.getUser().getUsername()));
1356
			else
1357
				res.setUser(dao.getEntityById(User.class, dto.getUser().getId()));
1358
		res.setRead(dto.hasRead());
1359
		res.setWrite(dto.hasWrite());
1360
		res.setModifyACL(dto.hasModifyACL());
1361
		return res;
1362
	}
1363

  
1364
	/* (non-Javadoc)
1365
	 * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsersByUserNameLike(java.lang.String)
1366
	 */
1367
	@Override
1368
	public List<UserDTO> getUsersByUserNameLike(String username) {
1369
		List<User> users = dao.getUsersByUserNameLike(username);
1370
		List<UserDTO> result = new ArrayList<UserDTO>();
1371
		for (User u : users)
1372
			result.add(u.getDTO());
1373
		return result;
1374

  
1375
	}
1376

  
1377
	/* (non-Javadoc)
1378
	 * @see gr.ebs.gss.server.ejb.ExternalAPI#addUserToGroup(java.lang.Long, java.lang.Long, java.lang.Long)
1379
	 */
1380
	@Override
1381
	public void addUserToGroup(Long userId, Long groupId, Long userToAddId) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException {
1382
		if (userId == null)
1383
			throw new ObjectNotFoundException("No user specified");
1384
		if (groupId == null)
1385
			throw new ObjectNotFoundException("No group specified");
1386
		if (userToAddId == null)
1387
			throw new ObjectNotFoundException("No user to add specified");
1388
		User user = dao.getEntityById(User.class, userId);
1389
		Group group = dao.getEntityById(Group.class, groupId);
1390
		if (!group.getOwner().equals(user))
1391
			throw new InsufficientPermissionsException();
1392
		User userToAdd = dao.getEntityById(User.class, userToAddId);
1393
		if (group.contains(userToAdd))
1394
			throw new DuplicateNameException("User already exists in group");
1395
		group.getMembers().add(userToAdd);
1396
		dao.update(group);
1397

  
1398
	}
1399

  
1400
	@Override
1401
	public void invalidateUserToken(Long userId) throws ObjectNotFoundException {
1402
		if (userId == null)
1403
			throw new ObjectNotFoundException("No user specified");
1404
		User user = dao.getEntityById(User.class, userId);
1405
		user.invalidateAuthToken();
1406
		return;
1407
	}
1408

  
1409
	@Override
1410
	public List<FolderDTO> getSharedRootFolders(Long userId) throws ObjectNotFoundException {
1411
		if (userId == null)
1412
			throw new ObjectNotFoundException("No user specified");
1413
		List<Folder> folders = dao.getSharedRootFolders(userId);
1414
		List<FolderDTO> result = new ArrayList<FolderDTO>();
1415
		for (Folder f : folders) {
1416
			FolderDTO dto = f.getDTO();
1417
			dto.setSubfolders(getSharedSubfolders(userId, f.getId()));
1418
			result.add(dto);
1419
		}
1420
		return result;
1421
	}
1422

  
1423
	/* (non-Javadoc)
1424
	 * @see gr.ebs.gss.server.ejb.ExternalAPI#removeMemberFromGroup(java.lang.Long, java.lang.Long, java.lang.Long)
1425
	 */
1426
	@Override
1427
	public void removeMemberFromGroup(Long userId, Long groupId, Long memberId) throws ObjectNotFoundException, InsufficientPermissionsException {
1428
		if (userId == null)
1429
			throw new ObjectNotFoundException("No user specified");
1430
		if (groupId == null)
1431
			throw new ObjectNotFoundException("No group specified");
1432
		if (memberId == null)
1433
			throw new ObjectNotFoundException("No member specified");
1434
		User owner = dao.getEntityById(User.class, userId);
1435
		Group group = dao.getEntityById(Group.class, groupId);
1436
		User member = dao.getEntityById(User.class, memberId);
1437
		if (!group.getOwner().equals(owner))
1438
			throw new InsufficientPermissionsException("User is not the owner of the group");
1439
		group.removeMemberFromGroup(member);
1440
		dao.update(group);
1441

  
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff