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