001: /***************************************************************
002: * This file is part of the [fleXive](R) project.
003: *
004: * Copyright (c) 1999-2007
005: * UCS - unique computing solutions gmbh (http://www.ucs.at)
006: * All rights reserved
007: *
008: * The [fleXive](R) project is free software; you can redistribute
009: * it and/or modify it under the terms of the GNU General Public
010: * License as published by the Free Software Foundation;
011: * either version 2 of the License, or (at your option) any
012: * later version.
013: *
014: * The GNU General Public License can be found at
015: * http://www.gnu.org/copyleft/gpl.html.
016: * A copy is found in the textfile GPL.txt and important notices to the
017: * license from the author are found in LICENSE.txt distributed with
018: * these libraries.
019: *
020: * This library is distributed in the hope that it will be useful,
021: * but WITHOUT ANY WARRANTY; without even the implied warranty of
022: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023: * GNU General Public License for more details.
024: *
025: * For further information about UCS - unique computing solutions gmbh,
026: * please see the company website: http://www.ucs.at
027: *
028: * For further information about [fleXive](R), please see the
029: * project website: http://www.flexive.org
030: *
031: *
032: * This copyright notice MUST APPEAR in all copies of the file!
033: ***************************************************************/package com.flexive.war.webdav;
034:
035: import javax.servlet.ServletInputStream;
036: import javax.servlet.http.HttpServletRequest;
037: import javax.servlet.http.HttpServletResponse;
038: import java.io.*;
039: import java.util.ArrayList;
040: import java.util.Date;
041:
042: /**
043: * FileSystem DAV context implementation
044: *
045: * @author Markus Plesser (markus.plesser@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
046: * @version $Rev: 1 $
047: */
048: public class FxDavFileSystemContext extends FxDavContext {
049:
050: private static FxDavFileSystemContext ddc = new FxDavFileSystemContext();
051: private static String BASE = "/home/pandur";
052:
053: /**
054: * Returns a singleton for the class.
055: *
056: * @return a singleton for the class.
057: */
058: public FxDavContext getSingleton() {
059: return ddc;
060: }
061:
062: /**
063: * Gets the resource stored under the given name, or null if the resource does not exist.
064: * <p/>
065: * The returned resource may be a collection (directory) or file.<br>
066: * The path starts always from the root entry, but there is no starting '/' character.<br>
067: * A empty String denotes the root collection.
068: *
069: * @param request the current request
070: * @param name the name of the resource, eg 'myFolder1/myFolder2/demo.html'
071: * @return the resource
072: */
073: public FxDavEntry getResource(HttpServletRequest request,
074: String name) {
075: if (name.equals("")) {
076: return new FxDavCollection("", new Date(), new Date());
077: }
078: String fname = BASE + File.separatorChar + name;
079: File f = new File(fname);
080: if (f.exists()) {
081: if (f.isDirectory())
082: return new FxDavCollection(f.getName(), new Date(f
083: .lastModified()), new Date(f.lastModified()));
084: return new FxDavResource(name, new Date(f.lastModified()),
085: new Date(f.lastModified()), f.length());
086: }
087: return null; //To change body of implemented methods use File | Settings | File Templates.
088: }
089:
090: /**
091: * Returns all childs of a given resource.
092: * <p/>
093: * A empty String denotes the root collection.
094: *
095: * @param request the current request
096: * @param name the name of the resource, eg 'myFolder1/myFolder2', 'myFolder1/File1.txt', 'File.txt'
097: * @return all childs of a given resource.
098: */
099: public FxDavEntry[] getChildren(HttpServletRequest request,
100: String name) {
101: ArrayList<FxDavEntry> entries = new ArrayList<FxDavEntry>(20);
102: File fBase = new File(BASE + File.separatorChar + name);
103: File[] all = fBase.listFiles();
104: for (File curr : all) {
105: if (curr.isDirectory()) {
106: entries.add(new FxDavCollection(curr.getName(),
107: new Date(curr.lastModified()), new Date(curr
108: .lastModified())));
109: } else if (curr.isFile()) {
110: entries.add(new FxDavResource(curr.getName(), new Date(
111: curr.lastModified()), new Date(curr
112: .lastModified()), curr.length()));
113: }
114: }
115: return entries.toArray(new FxDavEntry[0]);
116: }
117:
118: /**
119: * Serves a resource to the webdav client.
120: *
121: * @param request the current request
122: * @param response the response
123: * @param name the name of the resource, eg 'myFolder1/File1.txt'
124: * @throws java.io.IOException if the resource could not be served
125: */
126: public void serviceResource(HttpServletRequest request,
127: HttpServletResponse response, String name)
128: throws IOException {
129: FxDavEntry entry = getResource(request, name);
130: if (entry == null || entry.isCollection()) {
131: response.sendError(FxWebDavStatus.SC_NOT_FOUND);
132: return;
133: }
134: FxDavResource resource = (FxDavResource) entry;
135: File f = new File(BASE + File.separatorChar + name);
136: String ext = f.getAbsolutePath().lastIndexOf('.') > 0 ? f
137: .getAbsolutePath().substring(
138: f.getAbsolutePath().lastIndexOf('.') + 1)
139: : "unknown";
140: System.out.println("sending: " + f.getAbsolutePath() + " ext:"
141: + ext);
142: response.setContentLength((int) resource.getContentlength());
143: response.setContentType(FxWebDavUtils
144: .getContentTypeMapping(ext)
145: + ";charset=UTF-8");
146: FxWebDavUtils.setModifiedAtDate(response, resource
147: .getLastmodified());
148: response.setStatus(HttpServletResponse.SC_OK);
149: OutputStream out = null;
150: FileInputStream in = null;
151: try {
152: in = new FileInputStream(f);
153: out = response.getOutputStream();
154: byte[] buffer = new byte[1024];
155: int read;
156: while ((read = in.read(buffer)) != -1)
157: out.write(buffer, 0, read);
158: out.flush();
159: } finally {
160: try {
161: if (out != null)
162: out.close();
163: } catch (IOException e) {
164: e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
165: }
166: try {
167: if (in != null)
168: in.close();
169: } catch (IOException e) {
170: e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
171: }
172: }
173:
174: }
175:
176: /**
177: * Create a collection (Mkcol operation).
178: * <p/>
179: * MKCOL creates a new collection resource at the location specified by the Request-URI.
180: * If the resource identified by the Request-URI is non-null then the MKCOL MUST fail.
181: * During MKCOL processing, a server MUST make the Request-URI a member of its parent collection, unless the
182: * Request-URI is "/". If no such ancestor exists, the method MUST fail.<br>
183: * When the MKCOL operation creates a new collection resource, all ancestors MUST already exist, or the method MUST
184: * fail with a 409 (Conflict) status code. For example, if a request to create collection /a/b/c/d/ is made, and
185: * neither /a/b/ nor /a/b/c/ exists, the request must fail.<br>
186: * <br><br>
187: * Possible return codes:
188: * 201 (Created) - The collection or structured resource was created in its entirety.<br>
189: * 403 (Forbidden) - This indicates at least one of two conditions: 1) the server does not allow the creation of
190: * collections at the given location in its namespace, or 2) the parent collection of the Request-URI exists but
191: * cannot accept members.<br>
192: * 405 (Method Not Allowed) - MKCOL can only be executed on a deleted/non-existent resource.<br>
193: * 409 (Conflict) - A collection cannot be made at the Request-URI until one or more intermediate collections have
194: * been created.<br>
195: * 507 (Insufficient Storage) - The resource does not have sufficient space to record the state of the resource
196: * after the execution of this method.<br>
197: * 423 (Locked) - The resource is locked
198: *
199: * @param request the current request
200: * @param name the absolute name of the collection, eg 'folder1/folder2/new_folder'
201: * @return the status code, WebdavStatus.SC_CREATED if the operation was successfull
202: */
203: public int createCollection(HttpServletRequest request, String name) {
204: System.out.println("creating: "
205: + new File(BASE + File.separator + name)
206: .getAbsolutePath());
207: return new File(BASE + File.separator + name).mkdirs() ? FxWebDavStatus.SC_CREATED
208: : FxWebDavStatus.SC_INSUFFICIENT_SPACE_ON_RESOURCE;
209: }
210:
211: /**
212: * Creates a resource.
213: *
214: * @param path the absolute path of the new resource, eg 'folder1/folder2/file.txt'
215: * @param request the request containing the data for the resource
216: * @return the status code, WebdavStatus.SC_CREATED if the operation was successfull
217: */
218: public int createResource(HttpServletRequest request, String path) {
219: try {
220: File newFile = new File(BASE + File.separator + path);
221:
222: if (!newFile.createNewFile())
223: return FxWebDavStatus.SC_METHOD_FAILURE;
224: ServletInputStream in = null;
225: FileOutputStream out = null;
226: try {
227: in = request.getInputStream();
228: out = new FileOutputStream(newFile);
229: byte[] buffer = new byte[1024];
230: int read;
231: while ((read = in.read(buffer)) != -1) {
232: out.write(buffer, 0, read);
233: }
234: out.flush();
235: } finally {
236: try {
237: if (in != null)
238: in.close();
239: } catch (IOException e) {
240: e.printStackTrace();
241: }
242: try {
243: if (out != null)
244: out.close();
245: } catch (IOException e) {
246: e.printStackTrace();
247: }
248: }
249:
250: return FxWebDavStatus.SC_CREATED;
251: } catch (IOException e) {
252: return FxWebDavStatus.SC_METHOD_FAILURE;
253: }
254: }
255:
256: /**
257: * Moves a resource.
258: *
259: * @param src the absolute path of the source resource, eg 'folder1/folder2/file.txt'
260: * @param dest the absolute path of the destination resource, eg 'folder1/folder2/file_new.txt'
261: * @param request the request containing the data for the resource
262: */
263: public void moveResource(HttpServletRequest request, String src,
264: String dest) {
265: System.out
266: .println("moving "
267: + src
268: + "->"
269: + dest
270: + " success:"
271: + new File(BASE + File.separator + src)
272: .renameTo(new File(BASE
273: + File.separator + dest)));
274: }
275:
276: /**
277: * Copies a resource.
278: *
279: * @param src the absolute path of the source resource, eg 'folder1/folder2/file.txt'
280: * @param dest the absolute path of the destination resource, eg 'folder1/folder2/file_new.txt'
281: * @param request the request containing the data for the resource
282: * @return the status code, FxWebDavStatus.SC_OK if the operation was successfull
283: */
284: public int copyResource(HttpServletRequest request, String src,
285: String dest) {
286: return FxWebDavStatus.SC_NOT_IMPLEMENTED;
287: }
288:
289: /**
290: * Attempts to delete a file, with error checking.
291: *
292: * @param f The file to delete.
293: * @return True if sucessful.
294: */
295: private static boolean delete(File f) {
296:
297: if (!f.delete()) {
298: if (f.list().length != 0) {
299: File fa[] = f.listFiles();
300: for (File aFa : fa) {
301: if (!aFa.isDirectory())
302: aFa.delete();
303: else {
304: delete(aFa);
305: aFa.delete();
306: }
307: }
308: return delete(f);
309: }
310: return false;
311: }
312: return true;
313: }
314:
315: /**
316: * Deletes a resource.
317: *
318: * @param path the absolute path of the new resource, eg 'folder1/folder2/file.txt'
319: * @param request the request containing the data for the resource
320: * @return the status code, FxWebDavStatus.SC_OK if the operation was successful
321: */
322: public int deleteResource(HttpServletRequest request, String path) {
323: File f = new File(BASE + File.separatorChar + path);
324: if (!f.exists())
325: return FxWebDavStatus.SC_NOT_FOUND;
326: return delete(f) ? FxWebDavStatus.SC_OK
327: : FxWebDavStatus.SC_CONFLICT;
328: }
329: }
|