Imported changesets 6ad7cf34a8f5, d535941636f3, f3a4422f7b1a from the default branch
[pithos] / src / gr / ebs / gss / server / webdav / milton / GssFileResource.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.RpcException;
26 import gr.ebs.gss.server.domain.FileHeader;
27 import gr.ebs.gss.server.domain.User;
28 import gr.ebs.gss.server.ejb.TransactionHelper;
29
30 import java.io.BufferedInputStream;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.io.OutputStream;
34 import java.util.Date;
35 import java.util.Map;
36 import java.util.concurrent.Callable;
37
38 import org.apache.commons.io.IOUtils;
39 import org.jboss.remoting.transport.coyote.ClientAbortException;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 import com.bradmcevoy.http.Auth;
44 import com.bradmcevoy.http.CollectionResource;
45 import com.bradmcevoy.http.CopyableResource;
46 import com.bradmcevoy.http.DeletableResource;
47 import com.bradmcevoy.http.GetableResource;
48 import com.bradmcevoy.http.MoveableResource;
49 import com.bradmcevoy.http.PropFindableResource;
50 import com.bradmcevoy.http.PropPatchableResource;
51 import com.bradmcevoy.http.Range;
52 import com.bradmcevoy.http.Request;
53 import com.bradmcevoy.http.Request.Method;
54 import com.bradmcevoy.http.exceptions.BadRequestException;
55 import com.bradmcevoy.http.exceptions.ConflictException;
56 import com.bradmcevoy.http.exceptions.NotAuthorizedException;
57 import com.bradmcevoy.http.webdav.PropPatchHandler.Fields;
58
59
60 /**
61  * @author kman
62  *
63  */
64 public class GssFileResource extends GssResource implements CopyableResource, DeletableResource, GetableResource, MoveableResource, PropFindableResource, PropPatchableResource {
65         /**
66          * Size of file transfer buffer in bytes.
67          */
68         private static final int BUFFER_SIZE = 4096;
69
70         /**
71          * The output buffer size to use when serving resources.
72          */
73         protected int output = 2048;
74
75         /**
76          * The input buffer size to use when serving resources.
77          */
78         private int input = 2048;
79         
80         FileHeader file;
81         private static final Logger log = LoggerFactory.getLogger(GssFileResource.class);
82         /**
83          * @param host
84          * @param factory
85          * @param resource
86          */
87         public GssFileResource(String host, GSSResourceFactory factory, Object resource, User currentUser) {
88                 super(host, factory, resource);
89                 this.file = (FileHeader) resource;
90                 this.currentUser = currentUser;
91                 
92         }
93         @Override
94         public String checkRedirect(Request arg0) {
95                 // TODO Auto-generated method stub
96                 return null;
97         }
98         @Override
99         public Date getModifiedDate() {
100                 return file.getAuditInfo().getModificationDate();
101         }
102         @Override
103         public String getName() {
104                 return file.getName();
105         }
106         @Override
107         public String getUniqueId() {
108                 return "file:"+file.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                                  new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
116
117                                         @Override
118                                         public Void call() throws Exception {
119                                                 if(newFsParent.folder.getId().equals(file.getFolder().getId())){
120                                                         getService().updateFile(getCurrentUser().getId(), file.getId(), arg1, null, new Date(), null, null, null);
121                                                 }
122                                                 else{
123                                                         getService().moveFile(getCurrentUser().getId(), file.getId(), newFsParent.folder.getId(), arg1);
124                                                 }
125                                                 return null;
126                                         }
127                                         
128                                 });
129                                 GssFileResource.this.file = getService().getFile(getCurrentUser().getId(), file.getId());
130                                 
131                         } catch (InsufficientPermissionsException e) {
132                                 throw new NotAuthorizedException(this);
133                         } catch (ObjectNotFoundException e) {
134                                 throw new BadRequestException(this);
135                         } catch (DuplicateNameException e) {
136                                 throw new ConflictException(this);
137                         } catch (RpcException e) {
138                                 throw new RuntimeException("System error");
139                         } catch (GSSIOException e) {
140                                 throw new RuntimeException("Unable to Move");
141                         } catch (Exception e) {
142                                 throw new RuntimeException("Unable to Move");
143                         }
144         } else {
145             throw new RuntimeException("Destination is an unknown type. Must be a Folder, is a: " + newParent.getClass());
146         }
147                 
148         }
149         @Override
150         public void copyTo(final CollectionResource newParent, final String arg1) throws NotAuthorizedException, BadRequestException, ConflictException {
151                 if( newParent instanceof GssFolderResource ) {                  
152                         final GssFolderResource newFsParent = (GssFolderResource) newParent;
153                         try {
154                                  new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
155
156                                         @Override
157                                         public Void call() throws Exception {
158                                                 getService().copyFile(getCurrentUser().getId(), file.getId(), newFsParent.folder.getId(), arg1);
159                                                 return null;
160                                         }
161                                         
162                                 });
163                                  GssFileResource.this.file = getService().getFile(getCurrentUser().getId(), file.getId());
164                         } catch (InsufficientPermissionsException e) {
165                                 throw new NotAuthorizedException(this);
166                         } catch (ObjectNotFoundException e) {
167                                 throw new BadRequestException(this);
168                         } catch (DuplicateNameException e) {
169                                 throw new ConflictException(this);
170                         } catch (RpcException e) {
171                                 throw new RuntimeException("System error");
172                         } catch (GSSIOException e) {
173                                 throw new RuntimeException("Unable to Move");
174                         } catch (Exception e) {
175                                 throw new RuntimeException("Unable to Move");
176                         }
177         } else {
178             throw new RuntimeException("Destination is an unknown type. Must be a FsDirectoryResource, is a: " + newParent.getClass());
179         }
180                 
181         }
182         @Override
183         public void delete() throws NotAuthorizedException, ConflictException, BadRequestException {
184                 try {
185                         new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
186
187                                 @Override
188                                 public Void call() throws Exception {
189                                         getService().deleteFile(getCurrentUser().getId(), file.getId());
190                                         return null;
191                                 }
192                         });
193                 } catch (ObjectNotFoundException e) {
194                         throw new BadRequestException(this);                    
195                 } catch (InsufficientPermissionsException e) {
196                         throw new NotAuthorizedException(this);
197                 } catch (RpcException e) {
198                         throw new BadRequestException(this);
199                 }
200                 catch (Exception e) {                   
201                         throw new BadRequestException(this);
202                 }
203         }
204         @Override
205         public Long getContentLength() {
206                 return file.getCurrentBody().getFileSize();
207         }
208         @Override
209         public String getContentType(String preferredList ) {
210         return file.getCurrentBody().getMimeType();
211         }
212         @Override
213         public Long getMaxAgeSeconds(Auth arg0) {
214                 return factory.maxAgeSeconds( this );
215         }
216         @Override
217         public void sendContent(OutputStream out, Range range, Map<String, String> params, String contentType ) throws IOException {
218         InputStream in = null;
219         try {
220             in = getService().getFileContents(getCurrentUser().getId(), file.getId());
221             if( range != null ) {
222                 copy(in, out, range);
223             } else {
224                 copyRange(in, out);
225             }
226             out.flush();
227             IOUtils.closeQuietly( in );
228         } catch (ObjectNotFoundException e) {
229                         // TODO Auto-generated catch block
230                 } catch (InsufficientPermissionsException e) {
231                         // TODO Auto-generated catch block
232                 } catch (RpcException e) {
233                         // TODO Auto-generated catch block
234                 } 
235                 catch(ClientAbortException ex){
236                         //do nothing
237                 }
238                 finally {
239             IOUtils.closeQuietly( in );
240             IOUtils.closeQuietly( out );
241         }
242                 
243         }
244         
245         protected void copy(InputStream resourceInputStream, OutputStream ostream, Range range) throws IOException {
246                 IOException exception = null;
247                 InputStream istream = new BufferedInputStream(resourceInputStream, input);
248                 exception = copyRange(istream, ostream, range.getStart(), range.getFinish());
249                 // Clean up the input stream
250                 istream.close();
251                 // Rethrow any exception that has occurred
252                 if (exception != null)
253                         throw exception;
254         }
255         protected void copy(InputStream resourceInputStream, OutputStream ostream) throws IOException{
256                 IOException exception = null;
257                 InputStream istream = new BufferedInputStream(resourceInputStream, input);
258                 // Copy the input stream to the output stream
259                 exception = copyRange(istream, ostream);
260                 // Clean up the input stream
261                 istream.close();
262                 // Rethrow any exception that has occurred
263                 if (exception != null)
264                         throw exception;
265         }
266         
267         private IOException copyRange(InputStream istream, OutputStream ostream) {
268                 // Copy the input stream to the output stream
269                 IOException exception = null;
270                 byte buffer[] = new byte[input];
271                 int len = buffer.length;
272                 while (true)
273                         try {
274                                 len = istream.read(buffer);
275                                 if (len == -1)
276                                         break;
277                                 ostream.write(buffer, 0, len);
278                         } catch (IOException e) {
279                                 exception = e;
280                                 len = -1;
281                                 break;
282                         }
283                 return exception;
284         }
285         
286         private IOException copyRange(InputStream istream, OutputStream ostream, long start, long end) {
287                 log.debug("Serving bytes:" + start + "-" + end);
288                 try {
289                         istream.skip(start);
290                 } catch (IOException e) {
291                         return e;
292                 }
293                 IOException exception = null;
294                 long bytesToRead = end - start + 1;
295                 byte buffer[] = new byte[input];
296                 int len = buffer.length;
297                 while (bytesToRead > 0 && len >= buffer.length) {
298                         try {
299                                 len = istream.read(buffer);
300                                 if (bytesToRead >= len) {
301                                         ostream.write(buffer, 0, len);
302                                         bytesToRead -= len;
303                                 } else {
304                                         ostream.write(buffer, 0, (int) bytesToRead);
305                                         bytesToRead = 0;
306                                 }
307                         } catch (IOException e) {
308                                 exception = e;
309                                 len = -1;
310                         }
311                         if (len < buffer.length)
312                                 break;
313                 }
314                 return exception;
315         }
316         @Override
317         public Date getCreateDate() {
318                 // TODO Auto-generated method stub
319                 return file.getAuditInfo().getCreationDate();
320         }
321         @Override
322         public void setProperties(Fields arg0) {
323                 // TODO Auto-generated method stub
324                 
325         }
326         
327         
328         @Override
329         public boolean authorise(Request request, Method method, Auth auth) {
330         boolean result = factory.getSecurityManager().authorise(request, method, auth, this);
331         if(result){
332                 User user = getCurrentUser();
333                 //check permission
334                 try {
335                                 getService().getFile(user.getId(), file.getId());
336                         } catch (ObjectNotFoundException e) {
337                                 return false;
338                         } catch (InsufficientPermissionsException e) {
339                                 return false;
340                         } catch (RpcException e) {
341                                 return false;
342                         }
343                         return true;
344         }
345         return result;
346     }
347 }