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