Removed all DTO where possible
[pithos] / src / gr / ebs / gss / server / webdav / milton / GssFolderResource.java
1 /*
2  * Copyright 2011 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.webdav.milton;
20
21 import gr.ebs.gss.client.exceptions.DuplicateNameException;
22 import gr.ebs.gss.client.exceptions.GSSIOException;
23 import gr.ebs.gss.client.exceptions.InsufficientPermissionsException;
24 import gr.ebs.gss.client.exceptions.ObjectNotFoundException;
25 import gr.ebs.gss.client.exceptions.QuotaExceededException;
26 import gr.ebs.gss.client.exceptions.RpcException;
27 import gr.ebs.gss.server.domain.FileHeader;
28 import gr.ebs.gss.server.domain.Folder;
29 import gr.ebs.gss.server.domain.User;
30 import gr.ebs.gss.server.ejb.TransactionHelper;
31
32 import java.io.File;
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.io.OutputStream;
36 import java.net.URLDecoder;
37 import java.util.ArrayList;
38 import java.util.Date;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.concurrent.Callable;
42
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 import com.bradmcevoy.http.Auth;
47 import com.bradmcevoy.http.CollectionResource;
48 import com.bradmcevoy.http.CopyableResource;
49 import com.bradmcevoy.http.DeletableResource;
50 import com.bradmcevoy.http.GetableResource;
51 import com.bradmcevoy.http.LockInfo;
52 import com.bradmcevoy.http.LockResult;
53 import com.bradmcevoy.http.LockTimeout;
54 import com.bradmcevoy.http.LockToken;
55 import com.bradmcevoy.http.LockingCollectionResource;
56 import com.bradmcevoy.http.MakeCollectionableResource;
57 import com.bradmcevoy.http.MoveableResource;
58 import com.bradmcevoy.http.PropFindableResource;
59 import com.bradmcevoy.http.PutableResource;
60 import com.bradmcevoy.http.QuotaResource;
61 import com.bradmcevoy.http.Range;
62 import com.bradmcevoy.http.Request;
63 import com.bradmcevoy.http.Resource;
64 import com.bradmcevoy.http.XmlWriter;
65 import com.bradmcevoy.http.Request.Method;
66 import com.bradmcevoy.http.exceptions.BadRequestException;
67 import com.bradmcevoy.http.exceptions.ConflictException;
68 import com.bradmcevoy.http.exceptions.NotAuthorizedException;
69
70
71 /**
72  * @author kman
73  *
74  */
75 public class GssFolderResource extends GssResource implements MakeCollectionableResource, PutableResource, CopyableResource, DeletableResource, MoveableResource, PropFindableResource, LockingCollectionResource, GetableResource, QuotaResource{
76          private static final Logger log = LoggerFactory.getLogger(GssFolderResource.class);
77         Folder folder;
78         
79         /**
80          * @param host
81          * @param factory
82          * @param resource
83          */
84         public GssFolderResource(String host, GSSResourceFactory factory, Object resource, User currentUser) {
85                 super(host, factory, resource);
86                 folder=(Folder) resource;
87                 this.currentUser=currentUser;
88         }
89         @Override
90         public String checkRedirect(Request request) {
91                 if( factory.getDefaultPage() != null ) {
92             return request.getAbsoluteUrl() + "/" + factory.getDefaultPage();
93         } else {
94             return null;
95         }
96         }
97         @Override
98         public Date getModifiedDate() {
99                 if(folder!=null && folder.getAuditInfo()!=null)
100                         return folder.getAuditInfo().getModificationDate();
101                 return null;
102         }
103         @Override
104         public String getName() {
105                 return folder.getName();
106         }
107         @Override
108         public String getUniqueId() {
109                 return "folder:"+folder.getId().toString();
110         }
111         @Override
112         public void moveTo(final CollectionResource newParent, final String arg1) throws ConflictException, NotAuthorizedException, BadRequestException {
113                 if( newParent instanceof GssFolderResource ) {
114                         final GssFolderResource newFsParent = (GssFolderResource) newParent;
115                         try {
116                                 if(newFsParent.folder.getName().equals(folder.getParent().getName())){
117                                         if(!folder.getName().equals(arg1))
118                                                 new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
119         
120                                                         @Override
121                                                         public Void call() throws Exception {
122                                                                 factory.getService().updateFolder(getCurrentUser().getId(), folder.getId(), arg1, null, null);
123                                                                 return null;
124                                                         }
125                                                         
126                                                 });
127                                 }
128                                 else new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
129
130                                         @Override
131                                         public Void call() throws Exception {
132                                                 factory.getService().moveFolder(getCurrentUser().getId(), folder.getId(), newFsParent.folder.getId(), arg1);                                            
133                                                 return null;
134                                         }
135                                         
136                                 });
137                                 GssFolderResource.this.folder = factory.getService().getFolder(getCurrentUser().getId(), folder.getId());
138                                 
139                         } catch (InsufficientPermissionsException e) {
140                                 throw new NotAuthorizedException(this);
141                         } catch (ObjectNotFoundException e) {
142                                 throw new BadRequestException(this);
143                         } catch (DuplicateNameException e) {
144                                 throw new ConflictException(this);
145                         } catch (RpcException e) {
146                                 throw new RuntimeException("System error");
147                         } catch (GSSIOException e) {
148                                 throw new RuntimeException("Unable to Move");
149                         } catch (Exception e) {
150                                 throw new RuntimeException("Unable to Move");
151                         }
152         } else {
153             throw new RuntimeException("Destination is an unknown type. Must be a Folder, is a: " + newParent.getClass());
154         }
155                 
156         }
157         @Override
158         public void copyTo(final CollectionResource newParent, final String arg1) throws NotAuthorizedException, BadRequestException, ConflictException {
159                 if( newParent instanceof GssFolderResource ) {                  
160                         final GssFolderResource newFsParent = (GssFolderResource) newParent;
161                         try {
162                                  new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
163
164                                         @Override
165                                         public Void call() throws Exception {
166                                                 factory.getService().copyFolder(getCurrentUser().getId(), folder.getId(), newFsParent.folder.getId(), arg1);
167                                                 return null;
168                                         }
169                                         
170                                 });
171                                 GssFolderResource.this.folder = factory.getService().getFolder(getCurrentUser().getId(), folder.getId());
172                         } catch (InsufficientPermissionsException e) {
173                                 throw new NotAuthorizedException(this);
174                         } catch (ObjectNotFoundException e) {
175                                 throw new BadRequestException(this);
176                         } catch (DuplicateNameException e) {
177                                 throw new ConflictException(this);
178                         } catch (RpcException e) {
179                                 throw new RuntimeException("System error");
180                         } catch (GSSIOException e) {
181                                 throw new RuntimeException("Unable to Move");
182                         } catch (Exception e) {
183                                 throw new RuntimeException("Unable to Move");
184                         }
185         } else {
186             throw new RuntimeException("Destination is an unknown type. Must be a FsDirectoryResource, is a: " + newParent.getClass());
187         }
188                 
189         }
190         @Override
191         public CollectionResource createCollection(final String name) throws NotAuthorizedException, ConflictException, BadRequestException {
192                 ////log.info("CALLING CREATECOLLECTION:"+name);
193                 try {
194                         final Folder folderParent = folder;
195                         Folder created = new TransactionHelper<Folder>().tryExecute(new Callable<Folder>() {
196                                 @Override
197                                 public Folder call() throws Exception {
198                                         Folder f = factory.getService().createFolder(getCurrentUser().getId(), folder.getId(), name);
199                                         return f;
200                                 }
201                         });
202                         return new GssFolderResource(host, factory, created, getCurrentUser());
203                 } catch (DuplicateNameException e) {
204                         e.printStackTrace();
205                         // XXX If the existing name is a folder we should be returning
206                         // SC_METHOD_NOT_ALLOWED, or even better, just do the createFolder
207                         // without checking first and then deal with the exceptions.
208                         throw new ConflictException(this);
209                 } catch (InsufficientPermissionsException e) {
210                         e.printStackTrace();
211                         throw new NotAuthorizedException(this);
212                 } catch (ObjectNotFoundException e) {
213                         e.printStackTrace();
214                         return null;
215                 } catch (RpcException e) {
216                         e.printStackTrace();
217                         throw new RuntimeException("System Error");
218                 } catch (Exception e) {
219                         e.printStackTrace();
220                         throw new RuntimeException("System Error");
221                 }
222         }
223         @Override
224         public Resource child(String name) {
225                 for(Folder f : folder.getSubfolders())
226                         if(f.getName().equals(name))
227                                 return new GssFolderResource(host, factory, f, getCurrentUser());
228                 
229                         try {
230                                 for(FileHeader f : factory.getService().getFiles(folder.getOwner().getId(), folder.getId(), true))
231                                         if(f.getName().equals(name))
232                                                 return new GssFileResource(host, factory, f,getCurrentUser());
233                         } catch (ObjectNotFoundException e) {
234                                 // TODO Auto-generated catch block
235                                 e.printStackTrace();
236                         } catch (InsufficientPermissionsException e) {
237                                 // TODO Auto-generated catch block
238                                 e.printStackTrace();
239                         } catch (RpcException e) {
240                                 // TODO Auto-generated catch block
241                                 e.printStackTrace();
242                         }
243             ////log.info("CALLING CHILD return null");
244                 return null;
245         }
246         @Override
247         public List<? extends Resource> getChildren() {
248                 try {
249                         this.folder = factory.getService().getFolder(getCurrentUser().getId(), folder.getId());
250                 } catch (ObjectNotFoundException e) {
251                         // TODO Auto-generated catch block
252                         e.printStackTrace();
253                 } catch (InsufficientPermissionsException e) {
254                         // TODO Auto-generated catch block
255                         e.printStackTrace();
256                 } catch (RpcException e) {
257                         // TODO Auto-generated catch block
258                         e.printStackTrace();
259                 }
260                 List<GssResource> result = new ArrayList<GssResource>();
261                 for(Folder f : folder.getSubfolders())
262                         if(!f.isDeleted())
263                                 result.add(new GssFolderResource(host, factory, f, getCurrentUser()));
264                 try {
265                         for(FileHeader f : factory.getService().getFiles(getCurrentUser().getId(), folder.getId(), true))
266                                 result.add(new GssFileResource(host, factory, f,getCurrentUser()));
267                 } catch (ObjectNotFoundException e) {
268                         // TODO Auto-generated catch block
269                         e.printStackTrace();
270                 } catch (InsufficientPermissionsException e) {
271                         // TODO Auto-generated catch block
272                         e.printStackTrace();
273                 } catch (RpcException e) {
274                         // TODO Auto-generated catch block
275                         e.printStackTrace();
276                 }
277                 return result;
278         }
279         @Override
280         public Resource createNew(final String name, InputStream in, Long length, final String contentType ) throws IOException, ConflictException, NotAuthorizedException, BadRequestException {
281                 
282         File uploadedFile = null;
283         try {
284                         uploadedFile = factory.getService().uploadFile(in, getCurrentUser().getId());
285                 } catch (IOException ex) {
286                         throw new IOException(ex);
287                 } catch (ObjectNotFoundException e) {
288                         e.printStackTrace();
289                         throw new BadRequestException(this);
290                 } catch (RpcException e) {
291                         throw new RuntimeException("Unable to upload file");                    
292                 }
293                 final File uf = uploadedFile;
294                 try {
295                         String pathFolder = folder.getPath();
296                         if(!pathFolder.endsWith("/"))
297                                 pathFolder=pathFolder+"/";
298                         String fname = pathFolder+name;
299                         ////log.info("fname:"+fname+" "+URLDecoder.decode(fname));
300                         Object ff2;
301                         try{
302                                 ff2 = factory.getService().getResourceAtPath(folder.getOwner().getId(), URLDecoder.decode(fname), true);
303                         }
304                         catch(ObjectNotFoundException ex){
305                                 ff2=null;
306                         }
307                         final Object ff = ff2;
308                         FileHeader kmfile = null;
309                         if(ff != null && ff instanceof FileHeader){
310                                 kmfile = new TransactionHelper<FileHeader>().tryExecute(new Callable<FileHeader>() {
311                                         @Override
312                                         public FileHeader call()  throws Exception{
313                                                 return factory.getService().updateFileContents(getCurrentUser().getId(), ((FileHeader)ff).getId(),  contentType, uf.length(), uf.getAbsolutePath());
314                                         }
315                                 });
316                         }
317                         else
318                                 kmfile = new TransactionHelper<FileHeader>().tryExecute(new Callable<FileHeader>() {
319                                         @Override
320                                         public FileHeader call() throws Exception{
321                                                 return factory.getService().createFile(getCurrentUser().getId(), folder.getId(), name, contentType, uf.length(), uf.getAbsolutePath());
322                                         }
323                                 });
324                         return new GssFileResource(host, factory, kmfile, getCurrentUser());
325                 } catch (ObjectNotFoundException e) {
326                         e.printStackTrace();
327                         throw new BadRequestException(this);
328                 } catch (InsufficientPermissionsException e) {
329                         e.printStackTrace();
330                         throw new NotAuthorizedException(this);
331                 }
332                 catch (DuplicateNameException e) {
333                         // TODO Auto-generated catch block
334                         e.printStackTrace();
335                         throw new ConflictException(this);
336                 }
337                 catch(QuotaExceededException e){
338                         e.printStackTrace();
339                         throw new ConflictException(this);
340                 }
341                 catch(Exception e){
342                         e.printStackTrace();
343                         throw new RuntimeException("System Error");
344                 }
345         }
346         @Override
347         public void delete() throws NotAuthorizedException, ConflictException, BadRequestException {
348                 try {
349                         factory.getService().deleteFolder(getCurrentUser().getId(), folder.getId());
350                 } catch (InsufficientPermissionsException e) {
351                         e.printStackTrace();
352                         throw new NotAuthorizedException(this);
353                 } catch (ObjectNotFoundException e) {
354                         e.printStackTrace();
355                         throw new BadRequestException(this);
356                 } catch (RpcException e) {
357                         e.printStackTrace();
358                         throw new BadRequestException(this);
359                 }
360                 
361         }
362         @Override
363         public Date getCreateDate() {
364                 if(folder!=null && folder.getAuditInfo()!=null)
365                         return folder.getAuditInfo().getCreationDate();
366                 return null;
367         }
368         @Override
369         public LockToken createAndLock(final String name, LockTimeout timeout, LockInfo lockInfo ) throws NotAuthorizedException {
370                 FileHeader kmfile=null;
371                 try {
372                         kmfile = new TransactionHelper<FileHeader>().tryExecute(new Callable<FileHeader>() {
373                                 @Override
374                                 public FileHeader call() throws Exception {
375                                         return factory.getService().createEmptyFile(getCurrentUser().getId(), folder.getId(), name);
376                                 }
377                         });
378                 } catch (Exception e) {
379                         // TODO Auto-generated catch block
380                         e.printStackTrace();
381                 }
382         GssFileResource newRes = new GssFileResource( host, factory, kmfile ,getCurrentUser());
383         LockResult res = newRes.lock( timeout, lockInfo );
384         return res.getLockToken();
385                 
386         }
387         @Override
388         public Long getContentLength() {
389                 return null;
390         }
391         @Override
392         public String getContentType(String arg0) {
393                  return "text/html";
394         }
395         @Override
396         public Long getMaxAgeSeconds(Auth arg0) {
397                 // TODO Auto-generated method stub
398                 return null;
399         }
400         /**
401     * Will generate a listing of the contents of this directory, unless
402     * the factory's allowDirectoryBrowsing has been set to false.
403     *
404     * If so it will just output a message saying that access has been disabled.
405     *
406     * @param out
407     * @param range
408     * @param params
409     * @param contentType
410     * @throws IOException
411     * @throws NotAuthorizedException
412     */
413    public void sendContent( OutputStream out, Range range, Map<String, String> params, String contentType ) throws IOException, NotAuthorizedException {
414        String subpath = folder.getPath();//getFile().getCanonicalPath().substring( factory.getRoot().getCanonicalPath().length() ).replace( '\\', '/' );
415        String uri = "/" + factory.getContextPath() + subpath;
416        XmlWriter w = new XmlWriter( out );
417        w.open( "html" );
418        w.open( "body" );
419        w.begin( "h1" ).open().writeText( this.getName() ).close();
420        w.open( "table" );
421        for( Resource r : getChildren() ) {
422            w.open( "tr" );
423
424            w.open( "td" );
425            w.begin( "a" ).writeAtt( "href", uri + "/" + r.getName() ).open().writeText( r.getName() ).close();
426            w.close( "td" );
427
428            w.begin( "td" ).open().writeText( r.getModifiedDate() + "" ).close();
429            w.close( "tr" );
430        }
431        w.close( "table" );
432        w.close( "body" );
433        w.close( "html" );
434        w.flush();
435    }
436         @Override
437         public Long getQuotaAvailable() {
438                 if(getCurrentUser()!=null)
439                         try {
440                                 return factory.getService().getUserStatistics(getCurrentUser().getId()).getQuotaLeftSize();
441                         } catch (ObjectNotFoundException e) {
442                                 // TODO Auto-generated catch block
443                                 e.printStackTrace();
444                         } catch (RpcException e) {
445                                 // TODO Auto-generated catch block
446                                 e.printStackTrace();
447                         }
448                 return null;
449         }
450         @Override
451         public Long getQuotaUsed() {
452                 if(getCurrentUser()!=null)
453                         try {
454                                 return factory.getService().getUserStatistics(getCurrentUser().getId()).getFileSize();
455                         } catch (ObjectNotFoundException e) {
456                                 // TODO Auto-generated catch block
457                                 e.printStackTrace();
458                         } catch (RpcException e) {
459                                 // TODO Auto-generated catch block
460                                 e.printStackTrace();
461                         }
462                 return null;
463         }
464         
465         @Override
466         public boolean authorise(Request request, Method method, Auth auth) {
467         boolean result = factory.getSecurityManager().authorise(request, method, auth, this);
468         if(result){
469                 User user = getCurrentUser();
470                 //check permission
471                 try {
472                                 this.folder=factory.getService().getFolder(user.getId(), folder.getId());
473                         } catch (ObjectNotFoundException e) {
474                                 return false;
475                         } catch (InsufficientPermissionsException e) {
476                                 return false;
477                         } catch (RpcException e) {
478                                 return false;
479                         }
480                         return true;
481         }
482         return result;
483     }
484 }