2 * Copyright 2011 Electronic Business Systems Ltd.
4 * This file is part of GSS.
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.
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.
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/>.
19 package gr.ebs.gss.server.webdav.milton;
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;
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;
36 import java.util.concurrent.Callable;
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;
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;
64 public class GssFileResource extends GssResource implements CopyableResource, DeletableResource, GetableResource, MoveableResource, PropFindableResource, PropPatchableResource {
66 * Size of file transfer buffer in bytes.
68 private static final int BUFFER_SIZE = 4096;
71 * The output buffer size to use when serving resources.
73 protected int output = 2048;
76 * The input buffer size to use when serving resources.
78 private int input = 2048;
81 private static final Logger log = LoggerFactory.getLogger(GssFileResource.class);
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;
94 public String checkRedirect(Request arg0) {
95 // TODO Auto-generated method stub
99 public Date getModifiedDate() {
100 return file.getAuditInfo().getModificationDate();
103 public String getName() {
104 return file.getName();
107 public String getUniqueId() {
108 return "file:"+file.getId().toString();
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;
115 new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
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);
123 getService().moveFile(getCurrentUser().getId(), file.getId(), newFsParent.folder.getId(), arg1);
129 GssFileResource.this.file = getService().getFile(getCurrentUser().getId(), file.getId());
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");
145 throw new RuntimeException("Destination is an unknown type. Must be a Folder, is a: " + newParent.getClass());
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;
154 new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
157 public Void call() throws Exception {
158 getService().copyFile(getCurrentUser().getId(), file.getId(), newFsParent.folder.getId(), arg1);
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");
178 throw new RuntimeException("Destination is an unknown type. Must be a FsDirectoryResource, is a: " + newParent.getClass());
183 public void delete() throws NotAuthorizedException, ConflictException, BadRequestException {
185 new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
188 public Void call() throws Exception {
189 getService().deleteFile(getCurrentUser().getId(), file.getId());
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);
200 catch (Exception e) {
201 throw new BadRequestException(this);
205 public Long getContentLength() {
206 return file.getCurrentBody().getFileSize();
209 public String getContentType(String preferredList ) {
210 return file.getCurrentBody().getMimeType();
213 public Long getMaxAgeSeconds(Auth arg0) {
214 return factory.maxAgeSeconds( this );
217 public void sendContent(OutputStream out, Range range, Map<String, String> params, String contentType ) throws IOException {
218 InputStream in = null;
220 in = getService().getFileContents(getCurrentUser().getId(), file.getId());
221 if( range != null ) {
222 copy(in, out, range);
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
235 catch(ClientAbortException ex){
239 IOUtils.closeQuietly( in );
240 IOUtils.closeQuietly( out );
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
251 // Rethrow any exception that has occurred
252 if (exception != null)
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
262 // Rethrow any exception that has occurred
263 if (exception != null)
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;
274 len = istream.read(buffer);
277 ostream.write(buffer, 0, len);
278 } catch (IOException e) {
286 private IOException copyRange(InputStream istream, OutputStream ostream, long start, long end) {
287 log.debug("Serving bytes:" + start + "-" + end);
290 } catch (IOException e) {
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) {
299 len = istream.read(buffer);
300 if (bytesToRead >= len) {
301 ostream.write(buffer, 0, len);
304 ostream.write(buffer, 0, (int) bytesToRead);
307 } catch (IOException e) {
311 if (len < buffer.length)
317 public Date getCreateDate() {
318 // TODO Auto-generated method stub
319 return file.getAuditInfo().getCreationDate();
322 public void setProperties(Fields arg0) {
323 // TODO Auto-generated method stub
329 public boolean authorise(Request request, Method method, Auth auth) {
330 boolean result = factory.getSecurityManager().authorise(request, method, auth, this);
332 User user = getCurrentUser();
335 getService().getFile(user.getId(), file.getId());
336 } catch (ObjectNotFoundException e) {
338 } catch (InsufficientPermissionsException e) {
340 } catch (RpcException e) {