View Javadoc

1   /*
2    * Copyright (c) 2006-2007 Creative Sphere Limited.
3    * All rights reserved. This program and the accompanying materials
4    * are made available under the terms of the Eclipse Public License v1.0
5    * which accompanies this distribution, and is available at
6    * http://www.eclipse.org/legal/epl-v10.html
7    *
8    * Contributors:
9    *
10   *   Creative Sphere - initial API and implementation
11   *
12   */
13  package org.abstracthorizon.danube.webdav.fs;
14  
15  import org.abstracthorizon.danube.http.Status;
16  import org.abstracthorizon.danube.http.util.IOUtils;
17  import org.abstracthorizon.danube.webdav.ResourceAdapter;
18  import org.abstracthorizon.danube.webdav.lock.LockingMechanism;
19  import org.abstracthorizon.danube.webdav.util.NamespacesProvider;
20  import org.abstracthorizon.danube.webdav.util.SimpleNamespacesProvider;
21  import org.abstracthorizon.danube.webdav.xml.dav.DAVNamespace;
22  import org.abstracthorizon.danube.webdav.xml.dav.request.properties.RequestProperty;
23  import org.abstracthorizon.danube.webdav.xml.dav.response.properties.CreationDate;
24  import org.abstracthorizon.danube.webdav.xml.dav.response.properties.DisplayName;
25  import org.abstracthorizon.danube.webdav.xml.dav.response.properties.GetContentLength;
26  import org.abstracthorizon.danube.webdav.xml.dav.response.properties.GetContentType;
27  import org.abstracthorizon.danube.webdav.xml.dav.response.properties.GetETag;
28  import org.abstracthorizon.danube.webdav.xml.dav.response.properties.GetLastModified;
29  import org.abstracthorizon.danube.webdav.xml.dav.response.properties.LockDiscovery;
30  import org.abstracthorizon.danube.webdav.xml.dav.response.properties.ResourceType;
31  import org.abstracthorizon.danube.webdav.xml.dav.response.properties.ResponseProperty;
32  import org.abstracthorizon.danube.webdav.xml.dav.response.properties.SupportedLock;
33  
34  import java.io.File;
35  import java.io.FileInputStream;
36  import java.io.FileOutputStream;
37  import java.io.IOException;
38  import java.io.InputStream;
39  import java.io.OutputStream;
40  
41  /**
42   * Simple file system resource adapter
43   *
44   * @author Daniel Sendula
45   */
46  public class FileSystemWebDAVResourceAdapter implements ResourceAdapter {
47  
48      /** Root path of the files to be served */
49      protected File path;
50  
51      /** Default file property names */
52      protected static ResponseProperty[] filePropertyNames = new ResponseProperty[]{
53          new CreationDate(Status.OK),
54          new DisplayName(Status.OK),
55          new GetContentLength(Status.OK),
56          new GetContentType(Status.OK),
57          new GetETag(Status.OK),
58          new GetLastModified(Status.OK),
59          new LockDiscovery(Status.OK),
60          new ResourceType(Status.OK),
61          // new Source(null),
62          new SupportedLock(Status.OK)
63      };
64  
65      /** Default directory property names */
66      protected static ResponseProperty[] dirPropertyNames = new ResponseProperty[]{
67          new CreationDate(Status.OK),
68          new DisplayName(Status.OK),
69          new GetETag(Status.OK),
70          new GetLastModified(Status.OK),
71          new LockDiscovery(Status.OK),
72          new ResourceType(Status.OK),
73          // new Source(null),
74          new SupportedLock(Status.OK)
75      };
76  
77      /** Default file request properties */
78      protected static RequestProperty[] fileRequestProperties = new RequestProperty[]{
79          new org.abstracthorizon.danube.webdav.xml.dav.request.properties.CreationDate(null),
80          new org.abstracthorizon.danube.webdav.xml.dav.request.properties.DisplayName(null),
81          new org.abstracthorizon.danube.webdav.fs.properties.GetContentLength(null),
82          new org.abstracthorizon.danube.webdav.fs.properties.GetContentType(null),
83          new org.abstracthorizon.danube.webdav.xml.dav.request.properties.GetETag(null),
84          new org.abstracthorizon.danube.webdav.fs.properties.GetLastModified(null),
85          new org.abstracthorizon.danube.webdav.xml.dav.request.properties.LockDiscovery(null),
86          new org.abstracthorizon.danube.webdav.xml.dav.request.properties.ResourceType(null),
87          new org.abstracthorizon.danube.webdav.xml.dav.request.properties.SupportedLock(null, null)
88      };
89  
90      /** Default dir request properties */
91      protected static RequestProperty[] dirRequestProperties = new RequestProperty[]{
92          new org.abstracthorizon.danube.webdav.xml.dav.request.properties.CreationDate(null),
93          new org.abstracthorizon.danube.webdav.xml.dav.request.properties.DisplayName(null),
94          new org.abstracthorizon.danube.webdav.xml.dav.request.properties.GetETag(null),
95          new org.abstracthorizon.danube.webdav.fs.properties.GetLastModified(null),
96          new org.abstracthorizon.danube.webdav.xml.dav.request.properties.LockDiscovery(null),
97          new org.abstracthorizon.danube.webdav.xml.dav.request.properties.ResourceType(null),
98          new org.abstracthorizon.danube.webdav.xml.dav.request.properties.SupportedLock(null, null)
99      };
100 
101     /** Namespace provider to be used with this adapter */
102     protected NamespacesProvider namespacesProvider = new SimpleNamespacesProvider();
103 
104     /** Locking mechanism to be used with this adapter */
105     protected LockingMechanism lockingMechanism = new FSLockingMechanism();
106 
107     /** Default DAV namespace */
108     protected DAVNamespace davNamespace = new DAVNamespace();
109 
110     /**
111      * Constructor
112      */
113     public FileSystemWebDAVResourceAdapter() {
114         initHandlers();
115     }
116 
117     /**
118      * Constructor
119      * @param path root directory for files to be served from
120      */
121     public FileSystemWebDAVResourceAdapter(File path) {
122         setFilePath(path);
123         initHandlers();
124     }
125 
126     /**
127      * Initialises handlers
128      */
129     protected void initHandlers() {
130         davNamespace.setDAVFactory(new FSDAVFactory());
131         namespacesProvider.addNamespace(davNamespace.getURLString(), davNamespace.getPreferredPrefix(), davNamespace);
132     }
133 
134     /**
135      * Returns root file path
136      * @return root file path
137      */
138     public File getFilePath() {
139         return path;
140     }
141 
142     /**
143      * Sets root file path
144      * @param path root file path
145      */
146     public void setFilePath(File path) {
147         this.path = path;
148     }
149 
150     /**
151      * Returns namespace provider
152      * @return namespace provider
153      */
154     public NamespacesProvider getNamespacesProvider() {
155         return namespacesProvider;
156     }
157 
158     /**
159      * Sets namespace provider
160      * @param namespacesProvider namespace provider
161      */
162     public void setNamespacesProvider(NamespacesProvider namespacesProvider) {
163         this.namespacesProvider = namespacesProvider;
164     }
165 
166     /**
167      * Returns locking mechanism
168      * @return locking mechanism
169      */
170     public LockingMechanism getLockingMechanism() {
171         return lockingMechanism;
172     }
173 
174     /**
175      * Sets locking mechanism
176      * @param lockingMechanism locking mechanism
177      */
178     public void setLockingMechanism(LockingMechanism lockingMechanism) {
179         this.lockingMechanism = lockingMechanism;
180     }
181 
182     /**
183      * Returns {@link File} objects of supplied resource directory
184      * @return {@link File} objects of supplied resource directory
185      */
186     public Object[] collectionElements(Object resource) {
187         File dir = (File)resource;
188         return dir.listFiles();
189     }
190 
191     /**
192      * Copies source file to destination file
193      * @param source source file
194      * @param destination destination file
195      * @param recursive is it deep copy
196      */
197     public void copy(Object source, Object destination, boolean recursive) throws IOException {
198         File from = (File)source;
199         File to = (File)destination;
200         // TODO update IOUtils to return IOException
201         if (!IOUtils.copy(from, to, recursive)) {
202             throw new IOException("Cannot copy");
203         }
204     }
205 
206     /**
207      * Deletes a file
208      * @param resource file
209      * @throws IOException thrown if there is a problem with deletion of the resource
210      */
211     public void delete(Object resource) throws IOException {
212         boolean ok;
213         File file = (File)resource;
214         if (file.isDirectory()) {
215             // TODO update IOUtils to return IOException
216             ok = IOUtils.delete(file);
217         } else {
218             ok = file.delete();
219         }
220         if (!ok) {
221             throw new IOException("Cannot delete");
222         }
223     }
224 
225     /**
226      * Returns <code>true</code> if file exists
227      * @return <code>true</code> if file exists
228      */
229     public boolean exists(Object resource) {
230         File file = (File)resource;
231         return file.exists();
232     }
233 
234     /**
235      * Returns {@link File} object of given path startin from {@link #path}
236      * @param path path
237      * @return a file
238      */
239     public Object findResource(String path) {
240         File file = new File(this.path, path);
241         if (file.exists()) {
242             try {
243                 return file.getCanonicalFile();
244             } catch (IOException e) {
245             }
246         }
247         return file;
248     }
249 
250     /**
251      * Returns file's parent
252      * @param resource file
253      * @return file's parent
254      */
255     public Object findParentResource(Object resource) {
256         File file = (File)resource;
257         if (file.equals(path)) {
258             return null;
259         } else {
260             return file.getParentFile();
261         }
262     }
263 
264     /**
265      * Returns default request properties
266      * @param resource a file
267      * @return {@link #dirRequestProperties} or {@link #fileRequestProperties}
268      */
269     public RequestProperty[] getDefaultRequestProperties(Object resource) {
270         File file = (File)resource;
271         if (file.isDirectory()) {
272             return dirRequestProperties;
273         } else {
274             return fileRequestProperties;
275         }
276     }
277 
278     /**
279      * Returns default response properties
280      * @param resource a file
281      * @return {@link #dirPropertyNames} or {@link #filePropertyNames}
282      */
283     public ResponseProperty[] getDefaultResponseProperties(Object resource) {
284         File file = (File)resource;
285         if (file.isDirectory()) {
286             return dirPropertyNames;
287         } else {
288             return filePropertyNames;
289         }
290     }
291 
292     /**
293      * Returns {@link FileInputStream}
294      * @param resource a file
295      * @return {@link FileInputStream}
296      */
297     public InputStream getInputStream(Object resource) {
298         File file = (File)resource;
299         try {
300             return new FileInputStream(file);
301         } catch (IOException e) {
302             return null;
303         }
304     }
305 
306     /**
307      * Returns {@link RandomAccessFileRangeInputStream}
308      * @param resource a file
309      * @param from from offset
310      * @param length length in bytes
311      * @return {@link RandomAccessFileRangeInputStream}
312      */
313     public InputStream getInpusStream(Object resource, long from, long length) {
314         File file = (File)resource;
315         try {
316             return new RandomAccessFileRangeInputStream(file, from, length);
317         } catch (IOException e) {
318             return null;
319         }
320     }
321 
322     /**
323      * Returns {@link FileOutputStream}
324      * @param resource a file
325      * @return {@link FileOutputStream}
326      */
327     public OutputStream getOutputStream(Object resource) {
328         File file = (File)resource;
329         try {
330             return new FileOutputStream(file);
331         } catch (IOException e) {
332             return null;
333         }
334     }
335 
336     /**
337      * Returns {@link RandomAccessFileRangeOutputStream}
338      * @param resource a file
339      * @param from from offset
340      * @param length length in bytes
341      * @return {@link RandomAccessFileRangeOutputStream}
342      */
343     public OutputStream getOutputStream(Object resource, long from, long length) {
344         File file = (File)resource;
345         try {
346             return new RandomAccessFileRangeOutputStream(file, from, length);
347         } catch (IOException e) {
348             return null;
349         }
350     }
351 
352     /**
353      * Returns file's name
354      * @param resource file
355      * @return file's name
356      */
357     public String getResourceName(Object resource) {
358         File file = (File)resource;
359         return file.getName();
360     }
361 
362     /**
363      * Returns file's last modified timestamp as hex plus file's absolute path
364      * @param resource file
365      * @return file's last modified timestamp as hex plus file's absolute path
366      */
367     public String getResourceETag(Object resource) {
368         File file = (File)resource;
369         String pathString = path.getAbsolutePath();
370         String eTag = file.getAbsolutePath();
371         eTag = eTag.substring(pathString.length());
372         eTag = "W/\"" + Long.toHexString(file.lastModified()) + "-" + eTag + "\"";
373         return eTag;
374     }
375 
376     /**
377      * Returns <code>true</code> if file is a directory
378      * @param resource a file
379      * @return <code>true</code> if file is a directory
380      */
381     public boolean isCollection(Object resource) {
382         File file = (File)resource;
383         return file.isDirectory();
384     }
385 
386     /**
387      * Makes a directory
388      * @param resource a file
389      * @throws IOException thrown in there is a problem in making the file
390      */
391     public void makeCollection(Object resource) throws IOException {
392         File file = (File)resource;
393         if (!file.mkdir()) {
394             throw new IOException("Cannot create folder");
395         }
396     }
397 
398     /**
399      * Renames the file
400      * @param source source
401      * @param destination destination
402      * @throws IOException thrown if there is a problem with copying the file
403      */
404     public void move(Object source, Object destination) throws IOException {
405         File from = (File)source;
406         File to = (File)destination;
407         if (!from.renameTo(to)) {
408             throw new IOException("Cannot move");
409         }
410     }
411 
412     /**
413      * Returns file's last modified timestamp
414      * @param resource a file
415      * @return file's last modified timestamp
416      */
417     public long resourceCreated(Object resource) {
418         File file = (File)resource;
419         return file.lastModified();
420     }
421 
422     /**
423      * Returns file's last modified timestamp
424      * @param resource a file
425      * @return file's last modified timestamp
426      */
427     public long resourceLastModified(Object resource) {
428         File file = (File)resource;
429         return file.lastModified();
430     }
431 
432     /**
433      * Returns file's length
434      * @param resource a file
435      * @return file's length
436      */
437     public long resourceLength(Object resource) {
438         File file = (File)resource;
439         return file.length();
440     }
441 
442 }