Commit Diff


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 <propfind>
   private static final List<String> 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 &lt;prop&gt; 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<Element> 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<Element> 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 <a href="http://www.webdav.org/specs/rfc2518.html#dav.properties">RFC2518</a> 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<String> 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 &lt;set&gt; or &lt;remove&gt; 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<Element> requestedProperties) {
     // initialize the <propstat> 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 &lt;allprop&gt;, &lt;propnames&gt; or
+   * &lt;prop&gt;. If the element is &lt;prop&gt; it will go through the list of it's children
+   * and request the values. For &lt;allprop&gt; it will get values of all known properties and
+   * &lt;propnames&gt; 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 <propstat> 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