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