commit 7ce524315f1196f548be7dd412b2a88e8658ff6b from: leo date: Wed Jan 28 20:35:30 2009 UTC documentation updates commit - dc84d4e3207523dfebd9c47b12d2d56c87fb5ee6 commit + 7ce524315f1196f548be7dd412b2a88e8658ff6b blob - 673a2a9aef5ecaff2c19f0317fa21de8a46d2320 blob + d7f212d12b539192e910de200ea6849244f0e8a0 --- modules/webdav/src/main/java/com/thinkberg/webdav/CopyMoveBase.java +++ modules/webdav/src/main/java/com/thinkberg/webdav/CopyMoveBase.java @@ -29,17 +29,26 @@ import java.io.IOException; import java.text.ParseException; /** + * The body of all COPY or MOVE requests. As these requests are very similar, they are handles mainly + * by this class. Only the actual execution using the underlying VFS backend is done in sub classes. + * * @author Matthias L. Jugel * @version $Id$ */ public abstract class CopyMoveBase extends WebdavHandler { + /** + * Handle a COPY or MOVE request. + * + * @param request the servlet request + * @param response the servlet response + * @throws IOException if there is an error executing this request + */ public void service(HttpServletRequest request, HttpServletResponse response) throws IOException { boolean overwrite = getOverwrite(request); FileObject object = VFSBackend.resolveFile(request.getPathInfo()); FileObject targetObject = getDestination(request); - try { final LockManager lockManager = LockManager.getInstance(); LockManager.EvaluationResult evaluation = lockManager.evaluateCondition(targetObject, getIf(request)); @@ -62,7 +71,6 @@ public abstract class CopyMoveBase extends WebdavHandl return; } - if (null == targetObject) { response.sendError(HttpServletResponse.SC_BAD_REQUEST); return; @@ -82,15 +90,24 @@ public abstract class CopyMoveBase extends WebdavHandl } else { FileObject targetParent = targetObject.getParent(); if (!targetParent.exists() || - !FileType.FOLDER.equals(targetParent.getType())) { + !FileType.FOLDER.equals(targetParent.getType())) { response.sendError(HttpServletResponse.SC_CONFLICT); } response.setStatus(HttpServletResponse.SC_CREATED); } + // delegate the actual execution to a sub class copyOrMove(object, targetObject, getDepth(request)); } + /** + * Execute the actual filesystem operation. Must be implemented by sub classes. + * + * @param object the source object + * @param target the target object + * @param depth a depth for copy + * @throws FileSystemException if there is an error executing the request + */ protected abstract void copyOrMove(FileObject object, FileObject target, int depth) throws FileSystemException; } blob - d7233be643552cc949f8535d2bdc4aade8257493 blob + 6b9a23b2651b992848161e7e484c1a93ce95c23e --- modules/webdav/src/main/java/com/thinkberg/webdav/PropFindHandler.java +++ modules/webdav/src/main/java/com/thinkberg/webdav/PropFindHandler.java @@ -44,19 +44,20 @@ import java.util.List; * @version $Id$ */ public class PropFindHandler extends WebdavHandler { - private static final String TAG_MULTISTATUS = "multistatus"; - private static final String TAG_HREF = "href"; - private static final String TAG_RESPONSE = "response"; + private static final Log LOG = LogFactory.getLog(PropFindHandler.class); - private static final String TAG_ALLPROP = "allprop"; - private static final String TAG_PROPNAMES = "propnames"; - private static final String TAG_PROP = "prop"; - + // these tags are valid children elements of private static final List VALID_PROPFIND_TAGS = Arrays.asList( TAG_ALLPROP, TAG_PROPNAMES, TAG_PROP ); - private static final Log LOG = LogFactory.getLog(PropFindHandler.class); + /** + * Handle a PROPFIND request. + * + * @param request the servlet request + * @param response the servlet response + * @throws IOException if there is an error that cannot be handled normally + */ public void service(HttpServletRequest request, HttpServletResponse response) throws IOException { SAXReader saxReader = new SAXReader(); try { @@ -88,7 +89,6 @@ public class PropFindHandler extends WebdavHandler { writer.close(); } else { - LOG.error(object.getName().getPath() + " NOT FOUND"); response.sendError(HttpServletResponse.SC_NOT_FOUND); } break; @@ -100,14 +100,23 @@ public class PropFindHandler extends WebdavHandler { } } - private Document getMultiStatusResponse(FileObject object, - Element propEl, - URL baseUrl, - int depth) throws FileSystemException { + /** + * Create a multistatus response by requesting all properties and writing a response for each + * the found and the non-found properties + * + * @param object the context object the propfind request applies to + * @param propEl the <prop> element containing the actual properties + * @param baseUrl the base url of this server + * @param depth a depth argument for how deep the find will go + * @return an XML document that is the response + * @throws FileSystemException if there was an error executing the propfind request + */ + private Document getMultiStatusResponse(FileObject object, Element propEl, URL baseUrl, int depth) + throws FileSystemException { Document propDoc = DocumentHelper.createDocument(); propDoc.setXMLEncoding("UTF-8"); - Element multiStatus = propDoc.addElement(TAG_MULTISTATUS, "DAV:"); + Element multiStatus = propDoc.addElement(TAG_MULTISTATUS, NAMESPACE_DAV); FileObject[] children = object.findFiles(new DepthFileSelector(depth)); for (FileObject child : children) { Element responseEl = multiStatus.addElement(TAG_RESPONSE); blob - 50f915eb7b1c5158cd909b49560628c9b14048a8 blob + 73a27bd2954d3d6a6a64a20998f1e88f6d3b69e4 --- modules/webdav/src/main/java/com/thinkberg/webdav/PropPatchHandler.java +++ modules/webdav/src/main/java/com/thinkberg/webdav/PropPatchHandler.java @@ -43,18 +43,21 @@ import java.util.ArrayList; import java.util.List; /** - * Handle PROPPATCH requests. This currently a dummy only and will return a - * forbidden status for any attempt to modify or remove a property. + * Handle PROPPATCH requests. This will set, update or remove properties from a resource + * or collection. Only works if the underlying VFS backend supports filesystem attributes. * * @author Matthias L. Jugel */ public class PropPatchHandler extends WebdavHandler { private static final Log LOG = LogFactory.getLog(PropPatchHandler.class); - private static final String TAG_MULTISTATUS = "multistatus"; - private static final String TAG_HREF = "href"; - private static final String TAG_RESPONSE = "response"; - + /** + * Handle a PROPPATCH request. + * + * @param request the servlet request + * @param response the servlet response + * @throws IOException if there is an error that cannot be handled normally + */ public void service(HttpServletRequest request, HttpServletResponse response) throws IOException { FileObject object = VFSBackend.resolveFile(request.getPathInfo()); @@ -117,11 +120,21 @@ public class PropPatchHandler extends WebdavHandler { } } - private Document getMultiStatusResponse(FileObject object, List requestedProperties, URL baseUrl) throws FileSystemException { + /** + * Get a multistatus response for each of the property set/remove requests. + * + * @param object the context object the property requests apply to + * @param requestedProperties the properties that should be set or removed + * @param baseUrl the base url of this server + * @return an XML document that is the response + * @throws FileSystemException if there is an error setting or removing a property + */ + private Document getMultiStatusResponse(FileObject object, List requestedProperties, URL baseUrl) + throws FileSystemException { Document propDoc = DocumentHelper.createDocument(); propDoc.setXMLEncoding("UTF-8"); - Element multiStatus = propDoc.addElement(TAG_MULTISTATUS, "DAV:"); + Element multiStatus = propDoc.addElement(TAG_MULTISTATUS, NAMESPACE_DAV); Element responseEl = multiStatus.addElement(TAG_RESPONSE); try { URL url = new URL(baseUrl, URLEncoder.encode(object.getName().getPath(), "UTF-8")); blob - c4c58177f10fdcc3fa24ad733291fa87a7f918e5 blob + fff558b8b248571866a3aaee6facf33409cf0949 --- modules/webdav/src/main/java/com/thinkberg/webdav/WebdavHandler.java +++ modules/webdav/src/main/java/com/thinkberg/webdav/WebdavHandler.java @@ -43,6 +43,13 @@ public abstract class WebdavHandler { static final int SC_CREATED = 201; static final int SC_LOCKED = 423; static final int SC_MULTI_STATUS = 207; + protected static final String TAG_MULTISTATUS = "multistatus"; + protected static final String TAG_HREF = "href"; + protected static final String TAG_RESPONSE = "response"; + protected static final String TAG_ALLPROP = "allprop"; + protected static final String TAG_PROPNAMES = "propnames"; + protected static final String TAG_PROP = "prop"; + protected static final String NAMESPACE_DAV = "DAV:"; protected static URL getBaseUrl(HttpServletRequest request) { try { blob - cbb3dd87be7a24c053a38ccaf2ea67fb8008746b blob + 44d46201240bd840b72b76a41e895411c21ee520 --- modules/webdav/src/main/java/com/thinkberg/webdav/data/AbstractDavResource.java +++ modules/webdav/src/main/java/com/thinkberg/webdav/data/AbstractDavResource.java @@ -28,6 +28,10 @@ import java.util.Arrays; import java.util.List; /** + * This is a DAV resource. This class mainly handles the properties associated with a resource. + * Please see RFC2518 for + * information about necessary properties and their allowed values. + * * @author Matthias L. Jugel * @version $Id$ */ @@ -46,7 +50,6 @@ public abstract class AbstractDavResource { public static final String TAG_PROP_SET = "set"; public static final String TAG_PROP_REMOVE = "remove"; - // @see http://www.webdav.org/specs/rfc2518.html#dav.properties public static final String PROP_CREATION_DATE = "creationdate"; public static final String PROP_DISPLAY_NAME = "displayname"; public static final String PROP_GET_CONTENT_LANGUAGE = "getcontentlanguage"; @@ -60,10 +63,10 @@ public abstract class AbstractDavResource { public static final String PROP_SUPPORTED_LOCK = "supportedlock"; // non-standard properties - static final String PROP_QUOTA = "quota"; - static final String PROP_QUOTA_USED = "quotaused"; - static final String PROP_QUOTA_AVAILABLE_BYTES = "quota-available-bytes"; - static final String PROP_QUOTA_USED_BYTES = "quota-used-bytes"; + public static final String PROP_QUOTA = "quota"; + public static final String PROP_QUOTA_USED = "quotaused"; + public static final String PROP_QUOTA_AVAILABLE_BYTES = "quota-available-bytes"; + public static final String PROP_QUOTA_USED_BYTES = "quota-used-bytes"; // list of standard supported properties (for allprop/propname) public static final List ALL_PROPERTIES = Arrays.asList( @@ -86,6 +89,16 @@ public abstract class AbstractDavResource { this.object = object; } + /** + * Set or remove a properties. This method expects a list of xml elements that are the + * properties to be set or removed. These elements must not be detached from their + * original <set> or <remove> parent tags to be able to determine what + * should be done with the property. + * + * @param root the root of the result document + * @param requestedProperties the list of properties to work on + * @return returns the root of the result document + */ public Element setPropertyValues(Element root, List requestedProperties) { // initialize the element for 200 Element okPropStatEl = root.addElement(TAG_PROPSTAT); @@ -120,6 +133,16 @@ public abstract class AbstractDavResource { return root; } + /** + * Get property values. This method expects one of either <allprop>, <propnames> or + * <prop>. If the element is <prop> it will go through the list of it's children + * and request the values. For <allprop> it will get values of all known properties and + * <propnames> will return the names of all known properties. + * + * @param root the root of the result document + * @param propertyEl the prop, propname or allprop element + * @return the root of the result document + */ public Element getPropertyValues(Element root, Element propertyEl) { // initialize the for 200 Element okPropStatEl = root.addElement(TAG_PROPSTAT); @@ -181,6 +204,15 @@ public abstract class AbstractDavResource { return root; } + /** + * Return a specially encoded full qualified name for a namespace and name. + * As HTTP headers may only contain ascii, the namespace is base64 encoded if + * it exists. + * + * @param nameSpace the namespace + * @param name the name of the property + * @return the encoded attribute name + */ protected String getFQName(String nameSpace, String name) { String prefix = ""; if (!"DAV:".equals(nameSpace) && null != nameSpace && !"".equals(nameSpace)) { blob - e4bf2188cc86ff140c5b178f6e57d616f5f50200 blob + b35f1546ce602c3d61da817be48f2173bde2c13d --- modules/webdav/src/main/java/com/thinkberg/webdav/data/DavCollection.java +++ modules/webdav/src/main/java/com/thinkberg/webdav/data/DavCollection.java @@ -20,6 +20,8 @@ import org.apache.commons.vfs.FileObject; import org.dom4j.Element; /** + * A DAV collection is similar to a directory. + * * @author Matthias L. Jugel * @version $Id$ */ @@ -77,6 +79,7 @@ public class DavCollection extends DavResource { } protected boolean addQuotaAvailableBytesProperty(Element root, boolean ignoreValue) { + // TODO add correct handling of available quota root.addElement(PROP_QUOTA_AVAILABLE_BYTES).addText(Long.toString(Long.MAX_VALUE)); return true; } blob - 1b38af5d0cc408f34529520f0c39c4e41b574af3 blob + 21c179640b6c7713c45fc28e27fce2201aff5be4 --- modules/webdav/src/main/java/com/thinkberg/webdav/data/DavResource.java +++ modules/webdav/src/main/java/com/thinkberg/webdav/data/DavResource.java @@ -195,7 +195,8 @@ public class DavResource extends AbstractDavResource { } protected boolean addGetETagProperty(Element root, boolean ignoreValue) { - return false; + root.addElement(PROP_GET_ETAG, Util.getETag(object)); + return true; } protected boolean addGetLastModifiedProperty(Element root, boolean ignoreValue) { blob - 3048290ec50e533b9e6bc29c272b59405f156dad blob + 06d0ba45d0947de8c84d470d4bc1a1fd74c4346a --- src/main/resources/simplelog.properties +++ src/main/resources/simplelog.properties @@ -15,5 +15,5 @@ # org.apache.commons.logging.simplelog.defaultlog=error -org.apache.commons.logging.simplelog.log.com.thinkberg.vfs.s3=debug -org.apache.commons.logging.simplelog.log.com.thinkberg.webdav=debug \ No newline at end of file +org.apache.commons.logging.simplelog.log.com.thinkberg.vfs.s3=info +org.apache.commons.logging.simplelog.log.com.thinkberg.webdav=info \ No newline at end of file