You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xindice-dev@xml.apache.org by vg...@apache.org on 2007/05/25 03:43:43 UTC

svn commit: r541504 [5/7] - in /xml/xindice/trunk: ./ config/ java/scratchpad/webadmin/ java/src/org/apache/xindice/client/xmldb/embed/ java/src/org/apache/xindice/core/ java/src/org/apache/xindice/core/data/ java/src/org/apache/xindice/core/filer/ jav...

Modified: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/viewer/components/XUpdateCollectionViewer.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/webadmin/viewer/components/XUpdateCollectionViewer.java?view=diff&rev=541504&r1=541498&r2=541504
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/webadmin/viewer/components/XUpdateCollectionViewer.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/webadmin/viewer/components/XUpdateCollectionViewer.java Thu May 24 18:43:39 2007
@@ -34,134 +34,131 @@
 import org.apache.xindice.webadmin.viewer.*;
 import org.apache.xindice.webadmin.viewer.HtmlViewerComponent;
 import org.apache.xindice.xml.NamespaceMap;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 
 /**
  * Xindice Html Viewer for collection xupdate searches.
  * 
- * @avalon.component
- * @avalon.service type=HtmlCollectionViewer
- * @x-avalon.info name=xupdate
- * @x-avalon.lifestyle type=singleton
- *
  * @author <a href="mailto:jmetzner@apache.org">Jan Metzner</a>
  * @version $Id$
  */
-public class XUpdateCollectionViewer
-	extends HtmlViewerComponent
-	implements HtmlCollectionViewer {
-	
-	public void execute(HttpServletRequest req, HttpServletResponse res,
-    	Collection col)
-    	throws ServletException, IOException {
-    	
-		String path = col.getCanonicalName();
-    	String title = "XUpdate for "+path;
-    	
-    	ServletOutputStream output = startViewer(title, path, res);
-    	
-    	String xupdate = req.getParameter("xupdate");
-    	if(xupdate == null) {
-    		xupdate = "";
-    	} else if(xupdate.length() > 0) {
-			// do xupdate
-			try {
-				NodeSet result = col.queryCollection("XUpdate", xupdate,
-					new NamespaceMap());
-				printResult(result, output);
-			} catch (DBException e) {
-				// TODO Auto-generated catch block
-				e.printStackTrace();
-			} 
-		}
-    	
-    	printStartTable(title, output);
-    	printStartSingleTableBox(output);
-    	output.print(XUPDATE_FORM_START);
-    	output.print(xupdate);
-		output.print(XUPDATE_FORM_END);
-    	printEndSingleTableBox(output);
-    	printEndTable(output);
-    	
-    	output.println("<br />");
-		printStartTable("Examples", output);
-		printStartSingleTableBox(output);
-		output.println(XUPDATE_EXAMPLES);
-		printEndSingleTableBox(output);
-		printEndTable(output);
-    	
-    	finishViewer(output);
+public class XUpdateCollectionViewer extends HtmlViewerComponent implements HtmlCollectionViewer {
+
+    private static final Log log = LogFactory.getLog(XUpdateCollectionViewer.class);
+
+    public void execute(HttpServletRequest req, HttpServletResponse res, Collection col)
+            throws ServletException, IOException {
+
+        String path = col.getCanonicalName();
+        String title = "XUpdate for " + path;
+
+        ServletOutputStream output = startViewer(title, path, res);
+
+        String xupdate = req.getParameter("xupdate");
+        if(xupdate == null) {
+            xupdate = "";
+        } else if(xupdate.length() > 0) {
+            // do xupdate
+            try {
+                NodeSet result = col.queryCollection("XUpdate", xupdate, new NamespaceMap());
+                printResult(result, output);
+            } catch (DBException e) {
+                log.error(e);
+            }
+        }
+
+        printStartTable(title, output);
+        printStartSingleTableBox(output);
+        output.print(XUPDATE_FORM_START);
+        output.print(xupdate);
+        output.print(XUPDATE_FORM_END);
+        printEndSingleTableBox(output);
+        printEndTable(output);
+
+        output.println("<br />");
+        printStartTable("Examples", output);
+        printStartSingleTableBox(output);
+        output.println(XUPDATE_EXAMPLES);
+        printEndSingleTableBox(output);
+        printEndTable(output);
+
+        finishViewer(output);
+    }
+
+    private void printResult(NodeSet result, ServletOutputStream output) throws IOException {
+        if(result != null && result.hasMoreNodes()) {
+            Object node = result.getNextNode();
+            String modified;
+            if(node instanceof Node) {
+                modified = ((Node)node).getFirstChild().getNodeValue();
+            } else {
+                //	TODO print something, that makes sense
+                modified = "Sorry something went wrong!";
+            }
+            printStartTable("XUpdate Result", output);
+            printStartSingleTableBox(output);
+            output.println("Modified <b>"+modified+"</b> Nodes!");
+            printEndSingleTableBox(output);
+            printEndTable(output);
+            output.println("<br />");
+        }
     }
-    
-    protected void printResult(NodeSet result, ServletOutputStream output) 
-    	throws IOException {
-    	if(result != null && result.hasMoreNodes()) {
-    		Object node = result.getNextNode();
-			String modified;
-    		if(node instanceof Node) {
-				modified = ((Node)node).getFirstChild().getNodeValue();
-    		} else {
-				//	TODO print something, that makes sense
-    			modified = "Sorry something went wrong!";
-    		}
-			printStartTable("XUpdate Result", output);			
-			printStartSingleTableBox(output);
-			output.println("Modified <b>"+modified+"</b> Nodes!");
-			printEndSingleTableBox(output);
-			printEndTable(output);
-			output.println("<br />");
-    	}
+
+    private static final String XUPDATE_FORM_START =
+        "<form action=\"\" method=\"post\"> \n" +
+        "<table class=\"upload-form\"> \n" +
+        "<tr><td> \n" +
+        "<textarea name=\"xupdate\" cols=\"80\" rows=\"15\">\n" ;
+
+    private static final String XUPDATE_FORM_END =
+        "</textarea> \n" +
+        "</td></tr><tr><td> \n" +
+        "<input type=\"submit\" name=\"submit\" value=\"xupdate\" /> \n" +
+        "</td></tr></table></form> \n";
+
+    private static final String XUPDATE_EXAMPLES =
+        "<b>Basic XUpdate Insert Command</b>" +
+        "<pre>&lt;xupdate:modifications version=\"1.0\" \n" +
+        "		xmlns:xupdate=\"http://www.xmldb.org/xupdate\"&gt; \n\n" +
+        "   &lt;xupdate:insert-after select=\"/addresses/address[1]\" &gt; \n" +
+        "	  &lt;xupdate:element name=\"address\"&gt; \n" +
+        "		 &lt;xupdate:attribute name=\"id\"&gt;2&lt;/xupdate:attribute&gt; \n" +
+        "		 &lt;fullname&gt;John Smith&lt;/fullname&gt; \n" +
+        "		 &lt;born day='2' month='12' year='1974'/&gt; \n" +
+        "		 &lt;country&gt;Germany&lt;/country&gt; \n" +
+        "	 &lt;/xupdate:element&gt; \n\n" +
+        "   &lt;/xupdate:insert-after&gt; \n" +
+        "&lt;/xupdate:modifications&gt; \n" +
+        " </pre>" +
+        "<b>XUpdate Commands</b><ul>" +
+        "<li><code>xupdate:insert-before</code> " +
+        " - Inserts a new node in document order before the selected node.</li> \n" +
+        "<li><code>xupdate:insert-after</code>" +
+        " - Inserts a new node in document order after the selected node.</li> \n" +
+        "<li><code>xupdate:update</code>" +
+        " - Replaces all child nodes of the selected node with the specified nodes.</li> \n" +
+        "<li><code>xupdate:append</code>" +
+        " - Appends the specified node to the content of the selected node.</li> \n" +
+        "<li><code>xupdate:remove</code>" +
+        " - Remove the selected node</li> \n" +
+        "<li><code>xupdate:rename</code>" +
+        " - Renames the selected node</li> \n" +
+        "<li><code>xupdate:variable</code>" +
+        " - Defines a variable containing a node list that can be reused in later operations.</li> \n" +
+        "</ul><b>XUpdate Node Construction</b><ul>" +
+        "<li><code>xupdate:element</code>" +
+        " - Creates a new element in the document.</li> \n" +
+        "<li><code>xupdate:attribute</code>" +
+        " - Creates a new attribute node associated with an <code>xupdate:element</code>.</li> \n" +
+        "<li><code>xupdate:text</code>" +
+        " - Creates a text content node in the document.</li> \n" +
+        "<li><code>xupdate:processing-instruction</code>" +
+        " - Creates a processing instruction node in the document.</li> \n" +
+        "<li><code>xupdate:comment</code>" +
+        " - Creates a new comment node in the document.</li> </ul>\n";
+
+    protected String getName() {
+        return "xupdate";
     }
-    
-	protected static final String XUPDATE_FORM_START = 
-		"<form action=\"\" method=\"post\"> \n" +	
-		"<table class=\"upload-form\"> \n" +
-		"<tr><td> \n" + 
-		"<textarea name=\"xupdate\" cols=\"80\" rows=\"15\">\n" ;
-		
-	protected static final String XUPDATE_FORM_END =	
-		"</textarea> \n" +
-		"</td></tr><tr><td> \n" +
-		"<input type=\"submit\" name=\"submit\" value=\"xupdate\" /> \n" +
-		"</td></tr></table></form> \n";
-	
-	protected static final String XUPDATE_EXAMPLES =
-		"<b>Basic XUpdate Insert Command</b>" +
-		"<pre>&lt;xupdate:modifications version=\"1.0\" \n" +
-		"		xmlns:xupdate=\"http://www.xmldb.org/xupdate\"&gt; \n\n" +
-		"   &lt;xupdate:insert-after select=\"/addresses/address[1]\" &gt; \n" +
-		"	  &lt;xupdate:element name=\"address\"&gt; \n" +
-		"		 &lt;xupdate:attribute name=\"id\"&gt;2&lt;/xupdate:attribute&gt; \n" +
-		"		 &lt;fullname&gt;John Smith&lt;/fullname&gt; \n" +
-		"		 &lt;born day='2' month='12' year='1974'/&gt; \n" +
-		"		 &lt;country&gt;Germany&lt;/country&gt; \n" +
-		"	 &lt;/xupdate:element&gt; \n\n" +
-		"   &lt;/xupdate:insert-after&gt; \n" +
-		"&lt;/xupdate:modifications&gt; \n" +
-		" </pre>" +
-		"<b>XUpdate Commands</b><ul>" +
-		"<li><code>xupdate:insert-before</code> " +
-		" - Inserts a new node in document order before the selected node.</li> \n" +
-		"<li><code>xupdate:insert-after</code>" +
-		" - Inserts a new node in document order after the selected node.</li> \n" +
-		"<li><code>xupdate:update</code>" +
-		" - Replaces all child nodes of the selected node with the specified nodes.</li> \n" +
-		"<li><code>xupdate:append</code>" +
-		" - Appends the specified node to the content of the selected node.</li> \n" +
-		"<li><code>xupdate:remove</code>" +
-		" - Remove the selected node</li> \n" +
-		"<li><code>xupdate:rename</code>" +
-		" - Renames the selected node</li> \n" +
-		"<li><code>xupdate:variable</code>" +
-		" - Defines a variable containing a node list that can be reused in later operations.</li> \n" +
-		"</ul><b>XUpdate Node Construction</b><ul>" +
-		"<li><code>xupdate:element</code>" +
-		" - Creates a new element in the document.</li> \n" +
-		"<li><code>xupdate:attribute</code>" +
-		" - Creates a new attribute node associated with an <code>xupdate:element</code>.</li> \n" +
-		"<li><code>xupdate:text</code>" +
-		" - Creates a text content node in the document.</li> \n" +
-		"<li><code>xupdate:processing-instruction</code>" +
-		" - Creates a processing instruction node in the document.</li> \n" +
-		"<li><code>xupdate:comment</code>" +
-		" - Creates a new comment node in the document.</li> </ul>\n";		
 }

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/viewer/components/XUpdateCollectionViewer.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Thu May 24 18:43:39 2007
@@ -1 +1 @@
-Author Date Id Revision
+Id Revision Author Date

Added: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/DAVRequest.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/DAVRequest.java?view=auto&rev=541504
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/DAVRequest.java (added)
+++ xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/DAVRequest.java Thu May 24 18:43:39 2007
@@ -0,0 +1,263 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xindice.webadmin.webdav;
+
+import org.w3c.dom.Document;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.xml.sax.InputSource;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.ServletInputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+
+/**
+ * This is a wrapper class that provides additional DAV-specific functionality
+ */
+public class DAVRequest {
+    public static final int DEPTH_0 = 0;
+    public static final int DEPTH_1 = 1;
+    public static final int DEPTH_INFINITY = -1;
+
+    protected Document requestDoc;
+    private boolean documentInit = false;
+    protected String location;
+    private HttpServletRequest httpRequest;
+
+    private static final Log log = LogFactory.getLog(DAVRequest.class);
+
+    /**
+     * Creates new instance of DAVRequest based on incoming HTTP request.
+     *
+     * @param request HttpServletRequest
+     */
+    public DAVRequest(HttpServletRequest request) {
+        httpRequest = request;
+        location = getLocationPath();
+    }
+
+    /**
+     * Retreives request document if incoming request has any.
+     *
+     * @return Parsed request document if request body has one or null if
+     * request body was empty or does not have a valid XML.
+     * @throws IOException ServletInputStream IOException
+     */
+    public Document getRequestDoc() throws IOException {
+        if (!documentInit) {
+            documentInit = true;
+            requestDoc = parseRequestContent();
+        }
+
+        return requestDoc;
+    }
+
+    /**
+     * Wrapper method, gets servlet path info.
+     * @return Called servlet path.
+     */
+    public String getPath() {
+        return httpRequest.getPathInfo();
+    }
+
+    /**
+     * Wrapper method, gets HTTP request header.
+     * @param name Header name
+     * @return Header value
+     */
+    public String getHeader(String name) {
+        return httpRequest.getHeader(name);
+    }
+
+    /**
+     * Retrieves Overwrite header value from HTTP request. Possible values
+     * are "T" or "F" (true of false). By default value is "T".
+     *
+     * @return False if HTTP request has a header "Overwrite: F", true othewise.
+     */
+    public boolean getOverwrite() {
+        // Parsing overwrite header
+        boolean overwrite = true;
+        String overwriteHeader = httpRequest.getHeader("Overwrite");
+        if (overwriteHeader != null) {
+            overwrite = !overwriteHeader.equalsIgnoreCase("F");
+        }
+        return overwrite;
+    }
+
+    /**
+     * Retrieves Depth header value from HTTP request. Possible values
+     * are "0", "1", and "infinity". By default, value is "infinity".
+     *
+     * @return 0, 1, -1 for "0", "1", "infinity" header values respectively.
+     */
+    public int getDepth() {
+        String value = httpRequest.getHeader("Depth");
+        int depth = -1;
+        if ("0".equals(value)) {
+            depth = 0;
+        } else if ("1".equals(value)) {
+            depth = 1;
+        } else if (value == null || "infinity".equals(value)) {
+            depth = -1;
+        }
+
+        return depth;
+    }
+
+    /**
+     * Retrieves Destination header value from HTTP request. Its value is URL,
+     * it can be absolute or relative. This method returns only local path,
+     * deleting protocol, server name and context path.
+     *
+     * @return Local part of the destination path
+     */
+    public String getDestinationPath() {
+
+        String destinationPath = httpRequest.getHeader("Destination");
+        if (destinationPath == null) {
+            return null;
+        }
+
+        int protocolIndex = destinationPath.indexOf("://");
+        if (protocolIndex >= 0) {
+            // if the Destination URL contains the protocol, we can safely
+            // trim everything upto the first "/" character after "://"
+            int firstSeparator = destinationPath.indexOf("/", protocolIndex + 4);
+            if (firstSeparator < 0) {
+                destinationPath = "/";
+            } else {
+                destinationPath = destinationPath.substring(firstSeparator);
+            }
+        } else {
+            String hostName = httpRequest.getServerName();
+            if ((hostName != null) && (destinationPath.startsWith(hostName))) {
+                destinationPath = destinationPath.substring(hostName.length());
+            }
+
+            int portIndex = destinationPath.indexOf(":");
+            if (portIndex >= 0) {
+                destinationPath = destinationPath.substring(portIndex);
+            }
+
+            if (destinationPath.startsWith(":")) {
+                int firstSeparator = destinationPath.indexOf("/");
+                if (firstSeparator < 0) {
+                    destinationPath = "/";
+                } else {
+                    destinationPath = destinationPath.substring(firstSeparator);
+                }
+            }
+        }
+
+        String contextPath = httpRequest.getContextPath();
+        if ((contextPath != null) && (destinationPath.startsWith(contextPath))) {
+            destinationPath = destinationPath.substring(contextPath.length());
+        }
+
+        String pathInfo = httpRequest.getPathInfo();
+        if (pathInfo != null) {
+            String servletPath = httpRequest.getServletPath();
+            if ((servletPath != null) && (destinationPath.startsWith(servletPath))) {
+                destinationPath = destinationPath.substring(servletPath.length());
+            }
+        }
+
+        try {
+            destinationPath = URLDecoder.decode(destinationPath, "utf-8");
+        } catch (UnsupportedEncodingException e) {
+            // won't happen
+            log.error(e);
+            destinationPath = null;
+        }
+
+        return destinationPath;
+    }
+
+    /**
+     * Wrapper method, gets servlet context path.
+     * @return Called servlet context path.
+     */
+    public String getContextPath() {
+        return location;
+    }
+
+    private Document parseRequestContent() throws IOException {
+        if (httpRequest.getContentLength() != 0) {
+            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+            dbf.setNamespaceAware(true);
+            try {
+                DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
+                return documentBuilder.parse(new InputSource(httpRequest.getInputStream()));
+            } catch (IOException e) {
+                throw e;
+            } catch (Exception e) {
+                if (log.isWarnEnabled()) {
+                    log.warn("Cannot parse request document", e);
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * @return the path to calling servlet (not null and no ending '/')
+     */
+    private String getLocationPath() {
+        StringBuffer path = new StringBuffer();
+        path.append(httpRequest.getContextPath());
+        path.append(httpRequest.getServletPath());
+        if (path.length() > 0 && path.charAt(path.length() - 1) == '/') {
+            path.deleteCharAt(path.length() - 1);
+        }
+
+        return path.toString();
+    }
+
+    /**
+     * Wrapper method, gets servlet input stream.
+     * @return Servlet input stream.
+     */
+    public ServletInputStream getInputStream() throws IOException {
+        return httpRequest.getInputStream();
+    }
+
+    /**
+     * Wrapper method, gets HTTP request parameter.
+     *
+     * @param name Parameter name
+     * @return Parameter value
+     */
+    public String getParameter(String name) {
+        return httpRequest.getParameter(name);
+    }
+
+    /**
+     * Wrapper method, gets request protocol.
+     *
+     * @return Request protocol and version.
+     */
+    public String getProtocol() {
+        return httpRequest.getProtocol();
+    }
+}

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/DAVRequest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/DAVRequest.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision Author Date

Added: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/DAVResponse.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/DAVResponse.java?view=auto&rev=541504
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/DAVResponse.java (added)
+++ xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/DAVResponse.java Thu May 24 18:43:39 2007
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xindice.webadmin.webdav;
+
+import org.apache.xindice.webadmin.PartialResponse;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.ServletOutputStream;
+import java.io.IOException;
+
+/**
+ * This is a wrapper class that provides additional DAV-specific functionality
+ */
+public class DAVResponse {
+    public static final String DAV_NS = "DAV:";
+
+    protected final ServletOutputStream out;
+
+    private boolean isMultistatus;
+    private final HttpServletResponse response;
+    private String protocol;
+
+    private static final Log log = LogFactory.getLog(DAVResponse.class);
+
+    /**
+     * Creates new instance of DAVRequest.
+     *
+     * @param response HttpServletResponse
+     */
+    public DAVResponse(HttpServletResponse response) throws IOException {
+        this.response = response;
+        this.out = response.getOutputStream();
+    }
+
+    /**
+     * For multi-status responses, send a partial response. This method resets
+     * HTTP response status to 207 (Multi-Status).
+     *
+     * @param res partial response information
+     * @throws IOException Servlet IOException
+     */
+    public void sendMultiStatusResponse(PartialResponse res) throws IOException {
+        if (!isMultistatus) {
+            if (log.isDebugEnabled()) {
+                log.debug("Sending response for HREF " + res.getHref());
+            }
+            response.setStatus(WebdavStatus.SC_MULTI_STATUS);
+            out.println("<?xml version='1.0' encoding='utf-8' ?>");
+            out.println("<multistatus xmlns='DAV:'>");
+            isMultistatus = true;
+        }
+
+        out.println(res.toString());
+    }
+
+    /**
+     * For multi-status responses, close the response document. Method does not
+     * affect not multi-status responses.
+     * HTTP response status to 207 (Multi-Status).
+     *
+     * @throws IOException Servlet IOException
+     */
+    public void closeMultistatusResponse() throws IOException {
+        if (isMultistatus) {
+            out.println("</multistatus>");
+        }
+    }
+
+    /**
+     * Wrapper method, sets HTTP response status.
+     * @param status
+     */
+    public void setStatus(int status) {
+        response.setStatus(status);
+    }
+
+    /**
+     * Wrapper method, adds header to HTTP response.
+     * @param header Header name
+     * @param value Header value
+     */
+    public void addHeader(String header, String value) {
+        response.addHeader(header, value);
+    }
+
+    /**
+     * Wrapper method, adds date header to HTTP response.
+     * @param header Header name
+     * @param date Header value
+     */
+    public void addDateHeader(String header, long date) {
+        response.addDateHeader(header, date);
+    }
+
+    /**
+     * Wrapper method, sets HTTP response content type
+     * @param mimeType
+     */
+    public void setContentType(String mimeType) {
+        response.setContentType(mimeType);
+    }
+
+    /**
+     * Wrapper method, sets HTTP response content length
+     * @param contentLength
+     */
+    public void setContentLength(int contentLength) {
+        response.setContentLength(contentLength);
+    }
+
+    /**
+     * Wrapper method, returns HTTP response output stream
+     * @return Servlet output stream
+     */
+    public ServletOutputStream getOutputStream() throws IOException {
+        return response.getOutputStream();
+    }
+
+    /**
+     * Wrapper method, sends redirect
+     * @param redirect
+     */
+    public void sendRedirect(String redirect) throws IOException {
+        response.sendRedirect(redirect);
+    }
+
+    /**
+     * Sets protocol/version string that is used for multi status responses.
+     *
+     * @param protocol Protocol name and version (e.g. HTTP/1.1)
+     */
+    public void setProtocol(String protocol) {
+        this.protocol = protocol;
+    }
+
+    /**
+     * Returns protocol/version.
+     * @return Protocol name and version (e.g. HTTP/1.1)
+     */
+    public String getProtocol() {
+        return protocol;
+    }
+}

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/DAVResponse.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/DAVResponse.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision Author Date

Modified: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/WebdavStatus.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/WebdavStatus.java?view=diff&rev=541504&r1=541498&r2=541504
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/WebdavStatus.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/WebdavStatus.java Thu May 24 18:43:39 2007
@@ -19,106 +19,75 @@
 
 package org.apache.xindice.webadmin.webdav;
 
-import java.util.Hashtable;
+import java.util.Map;
+import java.util.HashMap;
 import javax.servlet.http.HttpServletResponse;
 
-// --------------------------------------------------------  WebdavStatus Class
-
-
 /**
- * Wraps the HttpServletResponse class to abstract the
- * specific protocol used.  To support other protocols
- * we would only need to modify this class and the
- * WebDavRetCode classes.
+ * Wraps the HttpServletResponse class to abstract the specific protocol
+ * used. To support other protocols we would only need to modify this class.
  *
  * @author              Marc Eaddy
  * @version             1.0, 16 Nov 1997
  */
 public class WebdavStatus {
 
-
-    // ----------------------------------------------------- Instance Variables
-
-
-    /**
-     * This Hashtable contains the mapping of HTTP and WebDAV
-     * status codes to descriptive text.  This is a static
-     * variable.
-     */
-    private static Hashtable mapStatusCodes = new Hashtable();
-
-
     // ------------------------------------------------------ HTTP Status Codes
 
-
     /**
      * Status code (200) indicating the request succeeded normally.
      */
     public static final int SC_OK = HttpServletResponse.SC_OK;
 
-
     /**
      * Status code (201) indicating the request succeeded and created
      * a new resource on the server.
      */
     public static final int SC_CREATED = HttpServletResponse.SC_CREATED;
 
-
     /**
      * Status code (202) indicating that a request was accepted for
      * processing, but was not completed.
      */
     public static final int SC_ACCEPTED = HttpServletResponse.SC_ACCEPTED;
 
-
     /**
      * Status code (204) indicating that the request succeeded but that
      * there was no new information to return.
      */
     public static final int SC_NO_CONTENT = HttpServletResponse.SC_NO_CONTENT;
 
-
     /**
      * Status code (301) indicating that the resource has permanently
      * moved to a new location, and that future references should use a
      * new URI with their requests.
      */
-    public static final int SC_MOVED_PERMANENTLY =
-        HttpServletResponse.SC_MOVED_PERMANENTLY;
-
+    public static final int SC_MOVED_PERMANENTLY = HttpServletResponse.SC_MOVED_PERMANENTLY;
 
     /**
      * Status code (302) indicating that the resource has temporarily
      * moved to another location, but that future references should
      * still use the original URI to access the resource.
      */
-    public static final int SC_MOVED_TEMPORARILY =
-        HttpServletResponse.SC_MOVED_TEMPORARILY;
-
+    public static final int SC_MOVED_TEMPORARILY = HttpServletResponse.SC_MOVED_TEMPORARILY;
 
     /**
      * Status code (304) indicating that a conditional GET operation
      * found that the resource was available and not modified.
      */
-    public static final int SC_NOT_MODIFIED =
-        HttpServletResponse.SC_NOT_MODIFIED;
-
+    public static final int SC_NOT_MODIFIED = HttpServletResponse.SC_NOT_MODIFIED;
 
     /**
      * Status code (400) indicating the request sent by the client was
      * syntactically incorrect.
      */
-    public static final int SC_BAD_REQUEST =
-        HttpServletResponse.SC_BAD_REQUEST;
-
+    public static final int SC_BAD_REQUEST = HttpServletResponse.SC_BAD_REQUEST;
 
     /**
      * Status code (401) indicating that the request requires HTTP
      * authentication.
      */
-    public static final int SC_UNAUTHORIZED =
-        HttpServletResponse.SC_UNAUTHORIZED;
-
+    public static final int SC_UNAUTHORIZED = HttpServletResponse.SC_UNAUTHORIZED;
 
     /**
      * Status code (403) indicating the server understood the request
@@ -126,46 +95,36 @@
      */
     public static final int SC_FORBIDDEN = HttpServletResponse.SC_FORBIDDEN;
 
-
     /**
      * Status code (404) indicating that the requested resource is not
      * available.
      */
     public static final int SC_NOT_FOUND = HttpServletResponse.SC_NOT_FOUND;
 
-
     /**
      * Status code (500) indicating an error inside the HTTP service
      * which prevented it from fulfilling the request.
      */
-    public static final int SC_INTERNAL_SERVER_ERROR =
-        HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
-
+    public static final int SC_INTERNAL_SERVER_ERROR = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
 
     /**
      * Status code (501) indicating the HTTP service does not support
      * the functionality needed to fulfill the request.
      */
-    public static final int SC_NOT_IMPLEMENTED =
-        HttpServletResponse.SC_NOT_IMPLEMENTED;
-
+    public static final int SC_NOT_IMPLEMENTED = HttpServletResponse.SC_NOT_IMPLEMENTED;
 
     /**
      * Status code (502) indicating that the HTTP server received an
      * invalid response from a server it consulted when acting as a
      * proxy or gateway.
      */
-    public static final int SC_BAD_GATEWAY =
-        HttpServletResponse.SC_BAD_GATEWAY;
-
+    public static final int SC_BAD_GATEWAY = HttpServletResponse.SC_BAD_GATEWAY;
 
     /**
      * Status code (503) indicating that the HTTP service is
      * temporarily overloaded, and unable to handle the request.
      */
-    public static final int SC_SERVICE_UNAVAILABLE =
-        HttpServletResponse.SC_SERVICE_UNAVAILABLE;
-
+    public static final int SC_SERVICE_UNAVAILABLE = HttpServletResponse.SC_SERVICE_UNAVAILABLE;
 
     /**
      * Status code (100) indicating the client may continue with
@@ -173,39 +132,34 @@
      * client that the initial part of the request has been
      * received and has not yet been rejected by the server.
      */
-    public static final int SC_CONTINUE = 100;
-
+    public static final int SC_CONTINUE = HttpServletResponse.SC_CONTINUE;
 
     /**
      * Status code (405) indicating the method specified is not
      * allowed for the resource.
      */
-    public static final int SC_METHOD_NOT_ALLOWED = 405;
-
+    public static final int SC_METHOD_NOT_ALLOWED = HttpServletResponse.SC_METHOD_NOT_ALLOWED;
 
     /**
      * Status code (409) indicating that the request could not be
      * completed due to a conflict with the current state of the
      * resource.
      */
-    public static final int SC_CONFLICT = 409;
-
+    public static final int SC_CONFLICT = HttpServletResponse.SC_CONFLICT;
 
     /**
      * Status code (412) indicating the precondition given in one
      * or more of the request-header fields evaluated to false
      * when it was tested on the server.
      */
-    public static final int SC_PRECONDITION_FAILED = 412;
-
+    public static final int SC_PRECONDITION_FAILED = HttpServletResponse.SC_PRECONDITION_FAILED;
 
     /**
      * Status code (413) indicating the server is refusing to
      * process a request because the request entity is larger
      * than the server is willing or able to process.
      */
-    public static final int SC_REQUEST_TOO_LONG = 413;
-
+    public static final int SC_REQUEST_ENTITY_TOO_LARGE = HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE;
 
     /**
      * Status code (415) indicating the server is refusing to service
@@ -213,48 +167,36 @@
      * not supported by the requested resource for the requested
      * method.
      */
-    public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415;
-
+    public static final int SC_UNSUPPORTED_MEDIA_TYPE = HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE;
 
     // -------------------------------------------- Extended WebDav status code
 
-
     /**
      * Status code (207) indicating that the response requires
      * providing status for multiple independent operations.
      */
     public static final int SC_MULTI_STATUS = 207;
-    // This one colides with HTTP 1.1
-    // "207 Parital Update OK"
-
 
     /**
-     * Status code (418) indicating the entity body submitted with
+     * Status code (422) indicating the entity body submitted with
      * the PATCH method was not understood by the resource.
      */
-    public static final int SC_UNPROCESSABLE_ENTITY = 418;
-    // This one colides with HTTP 1.1
-    // "418 Reauthentication Required"
-
+    public static final int SC_UNPROCESSABLE_ENTITY = 422;
 
     /**
-     * Status code (419) indicating that the resource does not have
+     * Status code (507) indicating that the resource does not have
      * sufficient space to record the state of the resource after the
      * execution of this method.
      */
-    public static final int SC_INSUFFICIENT_SPACE_ON_RESOURCE = 419;
-    // This one colides with HTTP 1.1
-    // "419 Proxy Reauthentication Required"
-
+    public static final int SC_INSUFFICIENT_SPACE_ON_RESOURCE = 507;
 
     /**
-     * Status code (420) indicating the method was not executed on
+     * Status code (424) indicating the method was not executed on
      * a particular resource within its scope because some part of
      * the method's execution failed causing the entire method to be
      * aborted.
      */
-    public static final int SC_METHOD_FAILURE = 420;
-
+    public static final int SC_FAILED_DEPENDENCY = 424;
 
     /**
      * Status code (423) indicating the destination resource of a
@@ -264,12 +206,13 @@
      */
     public static final int SC_LOCKED = 423;
 
-
-    // ------------------------------------------------------------ Initializer
-
-
+    /**
+     * This Hashtable contains the mapping of HTTP and WebDAV
+     * status codes to descriptive text.
+     */
+    private static Map mapStatusCodes = new HashMap();
     static {
-        // HTTP 1.0 tatus Code
+        // HTTP 1.1 status codes
         addStatusCodeMap(SC_OK, "OK");
         addStatusCodeMap(SC_CREATED, "Created");
         addStatusCodeMap(SC_ACCEPTED, "Accepted");
@@ -289,32 +232,26 @@
         addStatusCodeMap(SC_METHOD_NOT_ALLOWED, "Method Not Allowed");
         addStatusCodeMap(SC_CONFLICT, "Conflict");
         addStatusCodeMap(SC_PRECONDITION_FAILED, "Precondition Failed");
-        addStatusCodeMap(SC_REQUEST_TOO_LONG, "Request Too Long");
+        addStatusCodeMap(SC_REQUEST_ENTITY_TOO_LARGE, "Request Too Long");
         addStatusCodeMap(SC_UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type");
-        // WebDav Status Codes
+        // WebDav status sodes
         addStatusCodeMap(SC_MULTI_STATUS, "Multi-Status");
         addStatusCodeMap(SC_UNPROCESSABLE_ENTITY, "Unprocessable Entity");
-        addStatusCodeMap(SC_INSUFFICIENT_SPACE_ON_RESOURCE,
-                         "Insufficient Space On Resource");
-        addStatusCodeMap(SC_METHOD_FAILURE, "Method Failure");
+        addStatusCodeMap(SC_INSUFFICIENT_SPACE_ON_RESOURCE, "Insufficient Space On Resource");
+        addStatusCodeMap(SC_FAILED_DEPENDENCY, "Failed Dependency");
         addStatusCodeMap(SC_LOCKED, "Locked");
     }
 
-
-    // --------------------------------------------------------- Public Methods
-
-
     /**
      * Returns the HTTP status text for the HTTP or WebDav status code
-     * specified by looking it up in the static mapping.  This is a
-     * static function.
+     * specified by looking it up in the mapping.
      *
-     * @param   nHttpStatusCode [IN] HTTP or WebDAV status code
+     * @param   statusCode HTTP or WebDAV status code
      * @return  A string with a short descriptive phrase for the
      *                  HTTP status code (e.g., "OK").
      */
-    public static String getStatusText(int nHttpStatusCode) {
-        Integer intKey = new Integer(nHttpStatusCode);
+    public static String getStatusText(int statusCode) {
+        Integer intKey = new Integer(statusCode);
 
         if (!mapStatusCodes.containsKey(intKey)) {
             return "";
@@ -323,21 +260,15 @@
         }
     }
 
-
-    // -------------------------------------------------------- Private Methods
-
-
     /**
      * Adds a new status code -> status text mapping.  This is a static
      * method because the mapping is a static variable.
      *
-     * @param   nKey    [IN] HTTP or WebDAV status code
-     * @param   strVal  [IN] HTTP status text
+     * @param   key    HTTP or WebDAV status code
+     * @param   strVal HTTP status text
      */
-    private static void addStatusCodeMap(int nKey, String strVal) {
-        mapStatusCodes.put(new Integer(nKey), strVal);
+    private static void addStatusCodeMap(int key, String strVal) {
+        mapStatusCodes.put(new Integer(key), strVal);
     }
-
-
-};
+}
 

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/WebdavStatus.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Thu May 24 18:43:39 2007
@@ -1 +1 @@
-Author Date Id Revision
+Id Revision Author Date

Modified: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Copy.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Copy.java?view=diff&rev=541504&r1=541498&r2=541504
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Copy.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Copy.java Thu May 24 18:43:39 2007
@@ -20,73 +20,131 @@
 package org.apache.xindice.webadmin.webdav.components;
 
 import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map;
 
 import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 
-import org.apache.avalon.fortress.impl.DefaultContainer;
-import org.apache.avalon.framework.service.ServiceSelector;
 import org.apache.xindice.core.Collection;
 import org.apache.xindice.core.DBException;
 import org.apache.xindice.webadmin.util.DAVOperations;
-import org.apache.xindice.webadmin.webdav.*;
+import org.apache.xindice.webadmin.webdav.DAVRequest;
+import org.apache.xindice.webadmin.webdav.DAVResponse;
 import org.apache.xindice.webadmin.webdav.WebdavStatus;
+import org.apache.xindice.webadmin.PartialResponse;
+import org.apache.xindice.webadmin.Location;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 
-/** 
+/**
  * This class implements the Copy command for WebDAV operations on
- * Xindice. 
- * 
- * @avalon.component
- * @avalon.service type=DAVComponent
- * @x-avalon.info name=COPY
- * @x-avalon.lifestyle type=singleton
- * 
+ * Xindice. <br>
+ * <br>
+ * COPY commans instructs that the collection or resource be moved to
+ * the URI specified in the Destination header. It can overwrite
+ * existing collection/resource, and this behavior can be changed by
+ * using Overwrite flag in request header.<br>
+ * <br>
+ * COPY request for collection can have header Depth set to 0 or
+ * infinity, where infinity means that the entire subtree of child
+ * collections and resources will be copied to the new location,
+ * and 0 means only collection itself will be copied.<br>
+ * <br>
+ * Operation possible status codes include: <ul>
+ * <li>
+ * 201 (Created) - The source resource was successfully copied.  The
+ * copy operation resulted in the creation of a new resource.
+ * <li>
+ * 204 (No Content) - The source resource was successfully copied to a
+ * pre-existing destination resource.
+ * <li>
+ * 403 (Forbidden) - The source and destination URIs are the same.
+ * <li>
+ * 409 (Conflict) - A resource cannot be created at the destination
+ * until one or more intermediate collections have been created.
+ * <li>
+ * 412 (Precondition Failed) - The server was unable to maintain the
+ * liveness of the properties listed in the propertybehavior XML element
+ * or the Overwrite header is "F" and the state of the destination
+ * resource is non-null.
+ * </ul>
+ *
  * @author <a href="mailto:jmetzner@apache.org">Jan Metzner</a>
  * @author <a href="mailto:gianugo@apache.org">Gianugo Rabellino</a>
- * @version $Id$ 
+ * @version $Id$
  */
 
-public class Copy extends DefaultContainer implements DAVComponent {
+public class Copy implements DAVComponent {
+    private static final Log log = LogFactory.getLog(Copy.class);
 
-    public void execute(
-        HttpServletRequest req,
-        HttpServletResponse res,
-        Collection col)
-        throws ServletException, IOException {
-
-        try {
-            Collection parentCol = col.getParentCollection();
-            String resourceName = col.getName();
-            execute(req, res, parentCol, resourceName);
-        } catch (DBException e) {
-            throw new ServletException(e);
+    public void execute(DAVRequest req, DAVResponse res, Location target) throws ServletException, IOException {
+        if (target.isRoot()) {
+            res.setStatus(WebdavStatus.SC_FORBIDDEN);
+            return;
         }
+
+        Collection col = target.getCollection();
+        String name = target.getName();
+
+        if (col == null) {
+            res.setStatus(WebdavStatus.SC_NOT_FOUND);
+            return;
+        }
+
+        String dest = req.getDestinationPath();
+        if (dest == null) {
+            res.setStatus(WebdavStatus.SC_BAD_REQUEST);
+            return;
+        }
+
+        if (dest.equals(req.getPath())) {
+            res.setStatus(WebdavStatus.SC_FORBIDDEN);
+            return;
+        }
+
+        if (name == null) { // copying collection
+            try {
+                boolean deep = req.getDepth() != 0;
+                Map results = DAVOperations.copy(col, dest, req.getOverwrite(), deep);
+                interpretResults(results, res, dest);
+
+            } catch (DBException e) {
+                log.error("Failed to copy collection " + col.getCanonicalName(), e);
+                throw new ServletException(e);
+            }
+
+        } else { // copying resource
+            try {
+                int status = DAVOperations.copy(col, name, dest, req.getOverwrite());
+                res.setStatus(status);
+            } catch (DBException e) {
+                log.error("Failed to copy resource " + name + " from collection " + col.getCanonicalName(), e);
+                throw new ServletException(e);
+            }
+        }
+
     }
 
-    public void execute(
-        HttpServletRequest req,
-        HttpServletResponse res,
-        Collection parentCol,
-        String resourceName)
-        throws ServletException, IOException {
-
-        int status = WebdavStatus.SC_OK;
-        try {
-            DAVOperations davOps;
-            Object object = m_serviceManager.lookup(DAVOperations.ROLE);
-            if (object instanceof ServiceSelector) {
-                davOps =
-                    (DAVOperations) ((ServiceSelector)object).select(
-                        "dav-operations");
-            } else {
-                davOps = (DAVOperations)object;
+    private void interpretResults(Map results, DAVResponse res, String dest) throws IOException {
+        for (Iterator i = results.keySet().iterator(); i.hasNext(); ) {
+            String url = (String) i.next();
+            int status = ((Integer) results.get(url)).intValue();
+            if (url.equals(dest)) {
+                res.setStatus(status);
+                return;
             }
-            status = davOps.copy(req, parentCol, resourceName);
-        } catch (Exception e) {
-            e.printStackTrace();
-            throw new ServletException(e);
+
+            /*
+             * If an error in executing the COPY method occurs with a resource other
+             * than the resource identified in the Request-URI then the response
+             * MUST be a 207 (Multi-Status).
+             */
+            PartialResponse part = new PartialResponse(dest);
+            String st = res.getProtocol() + " " + status + " " + WebdavStatus.getStatusText(status);
+            part.addContent("status", st);
+            res.sendMultiStatusResponse(part);
         }
-        res.setStatus(status);
+
+        res.closeMultistatusResponse();
     }
 }

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Copy.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Thu May 24 18:43:39 2007
@@ -1 +1 @@
-Author Date Id Revision
+Id Revision Author Date

Added: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/DAVComponent.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/DAVComponent.java?view=auto&rev=541504
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/DAVComponent.java (added)
+++ xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/DAVComponent.java Thu May 24 18:43:39 2007
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * CVS $Id$
+ */
+
+package org.apache.xindice.webadmin.webdav.components;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+
+import org.apache.xindice.webadmin.webdav.DAVRequest;
+import org.apache.xindice.webadmin.webdav.DAVResponse;
+import org.apache.xindice.webadmin.Location;
+
+/**
+ * The main WebDAV interface for requests to different kind
+ * of resources.
+ *
+ * @author <a href="gianugo@apache.org">Gianugo Rabellino</a>
+ * @version $Id$
+ */
+public interface DAVComponent {
+
+    /**
+     * Executes request to a target location, that can be either root ("/"),
+     * collection, resource or an unknown location.
+     *
+     * @param req WebDAV request
+     * @param res WebDAV servlet
+     * @param target target location
+     */
+    public void execute(DAVRequest req, DAVResponse res, Location target) throws ServletException, IOException;
+
+}

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/DAVComponent.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/DAVComponent.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision Author Date

Modified: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Delete.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Delete.java?view=diff&rev=541504&r1=541498&r2=541504
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Delete.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Delete.java Thu May 24 18:43:39 2007
@@ -22,77 +22,85 @@
 import java.io.IOException;
 
 import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 
-import org.apache.avalon.fortress.impl.DefaultContainer;
 import org.apache.xindice.core.Collection;
 import org.apache.xindice.core.DBException;
-import org.apache.xindice.webadmin.webdav.*;
+import org.apache.xindice.core.FaultCodes;
+import org.apache.xindice.core.Database;
 import org.apache.xindice.webadmin.webdav.WebdavStatus;
+import org.apache.xindice.webadmin.webdav.DAVResponse;
+import org.apache.xindice.webadmin.webdav.DAVRequest;
+import org.apache.xindice.webadmin.Location;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 
-/** 
+/**
  * This class implements the Delete command for WebDAV operations on
- * Xindice. 
- * 
- * @avalon.component
- * @avalon.service type=DAVComponent
- * @x-avalon.info name=DELETE
- * @x-avalon.lifestyle type=singleton
- * 
+ * Xindice.<br>
+ * <br>
+ * DELETE command deletes target collection or resource. For collections,
+ * it deletes the entire subtree, so Depth header in request cannot be
+ * 0 or 1, but it can be omitted.<br>
+ * <br>
+ * The default success status code is 204 (No Content)
+ *
  * @author <a href="mailto:jmetzner@apache.org">Jan Metzner</a>
  * @author <a href="mailto:gianugo@apache.org">Gianugo Rabellino</a>
- * @version $Id $ 
+ * @version $Id $
  */
 
-public class Delete extends DefaultContainer implements DAVComponent {
+public class Delete implements DAVComponent {
+    private final Log log = LogFactory.getLog(Delete.class);
 
-    public void execute(
-        HttpServletRequest req,
-        HttpServletResponse res,
-        Collection col)
-        throws ServletException, IOException {
-
-        try {
-            Collection parentCol = col.getParentCollection();
-            parentCol.dropCollection(col);
-            res.setStatus(WebdavStatus.SC_NO_CONTENT);
-        } catch (DBException e) {
-            throw new ServletException(e);
+    public void execute(DAVRequest req, DAVResponse res, Location target) throws ServletException, IOException {
+        if (target.isRoot()) {
+            res.setStatus(WebdavStatus.SC_FORBIDDEN);
+            return;
         }
 
-    }
+        Collection col = target.getCollection();
+        String name = target.getName();
 
-    public void execute(
-        HttpServletRequest req,
-        HttpServletResponse res,
-        Collection parentCol,
-        String resourceName)
-        throws ServletException, IOException {
-
-        Object object = null;
-        try {
-            object = parentCol.getEntry(resourceName);
-        } catch (DBException e) {
-            if (this.getLogger().isDebugEnabled()) {
-                this.getLogger().debug("could not get entry " + resourceName);
-            }
-            object = null;
+        if (col == null) {
+            res.setStatus(WebdavStatus.SC_NOT_FOUND);
+            return;
         }
 
-        if (object == null) {
-            res.setStatus(WebdavStatus.SC_NOT_FOUND);
-        } else {
+        if (col instanceof Database) {
+            res.setStatus(WebdavStatus.SC_FORBIDDEN);
+            return;
+        }
+
+        if (req.getDepth() != DAVRequest.DEPTH_INFINITY) {
+            res.setStatus(WebdavStatus.SC_BAD_REQUEST);
+            return;
+        }
+
+        // TODO: set SC_FORBIDDEN for system collections
+        if (name == null) { // deleting collection
             try {
-                parentCol.remove(resourceName);
-                if (this.getLogger().isDebugEnabled()) {
-                    this.getLogger().debug(
-                        "entry " + resourceName + " deleted");
-                }
-                res.setStatus(WebdavStatus.SC_NO_CONTENT);
+                col.getDatabase().dropCollection(col);
             } catch (DBException e) {
+                log.error("Failed to delete collection " + col.getCanonicalName(), e);
                 throw new ServletException(e);
             }
+        } else { // deleting resource
+            try {
+                col.remove(name);
+                if (log.isDebugEnabled()) {
+                    log.debug("entry " + name + " deleted");
+                }
+            } catch (DBException e) {
+                if (e.faultCode == FaultCodes.COL_DOCUMENT_NOT_FOUND) {
+                    res.setStatus(WebdavStatus.SC_NOT_FOUND);
+                    return;
+                } else {
+                    log.error("Failed to delete resource " + name + " from collection " + col.getCanonicalName(), e);
+                    throw new ServletException(e);
+                }
+            }
         }
+        
+        res.setStatus(WebdavStatus.SC_NO_CONTENT);
     }
 }

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Delete.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Thu May 24 18:43:39 2007
@@ -1 +1 @@
-Author Date Id Revision
+Id Revision Author Date

Modified: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Get.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Get.java?view=diff&rev=541504&r1=541498&r2=541504
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Get.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Get.java Thu May 24 18:43:39 2007
@@ -23,110 +23,92 @@
 import java.io.OutputStream;
 
 import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.avalon.fortress.impl.DefaultContainer;
-import org.apache.avalon.framework.service.ServiceException;
 import org.apache.xindice.core.Collection;
 import org.apache.xindice.core.DBException;
-import org.apache.xindice.core.data.Key;
-import org.apache.xindice.core.data.Record;
+import org.apache.xindice.core.data.Entry;
 import org.apache.xindice.webadmin.util.MimeTable;
-import org.apache.xindice.webadmin.util.MimeTableImpl;
-import org.apache.xindice.webadmin.webdav.*;
+import org.apache.xindice.webadmin.webdav.DAVRequest;
+import org.apache.xindice.webadmin.webdav.DAVResponse;
+import org.apache.xindice.webadmin.Location;
 import org.apache.xindice.xml.TextWriter;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.w3c.dom.Document;
 
-/** 
- * This class implements the Get command for WebDAV operations on
- * Xindice. 
- * 
- * @avalon.component
- * @avalon.service type=DAVComponent
- * @x-avalon.info name=GET
- * @x-avalon.lifestyle type=singleton
- * 
+/**
+ * This class implements the Get HTTP command for WebDAV operations on
+ * Xindice.
+ *
  * @author <a href="mailto:jmetzner@apache.org">Jan Metzner</a>
  * @author <a href="mailto:gianugo@apache.org">Gianugo Rabellino</a>
- * @version $Id$ 
+ * @version $Id$
  */
 
-public class Get extends DefaultContainer implements DAVComponent {  
+public class Get implements DAVComponent {
 
-  public void execute(HttpServletRequest req, HttpServletResponse res,
-    Collection col) throws ServletException, IOException {
+    private static final Log log = LogFactory.getLog(Get.class);
+
+    public void execute(DAVRequest req, DAVResponse res, Location target) throws ServletException, IOException {
+        if (target.getName() == null) {
+            // test if viewer is already specified
+            String viewer = req.getParameter("viewer");
+            if (viewer != null && viewer.length() != 0) {
+                res.setStatus(HttpServletResponse.SC_NOT_IMPLEMENTED);
+            }
+
+            if (log.isDebugEnabled()) {
+                log.debug("WEBDAV Get redirected to HtmlViewer");
+            }
+
+            //	redirect if path does not end with /
+            String reqPath = req.getPath();
+            if (reqPath == null || !reqPath.endsWith("/")) {
+                if (reqPath == null) {
+                    reqPath = "";
+                }
+                String redirect = req.getContextPath() + reqPath + "/?viewer=default";
+                res.sendRedirect(redirect);
+            } else {
+                res.sendRedirect("?viewer=default");
+            }
 
-    // test if viewer is already specified
-    String viewer = req.getParameter("viewer");
-    if(viewer != null && viewer.length() != 0) {
-      res.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
-    }
-    
-    if (this.getLogger().isDebugEnabled()) {
-      this.getLogger().debug("WEBDAV Get redirected to HtmlViewer");
-    }
-	
-	//	redirect if path does not end with /
-	String reqPath = req.getPathInfo();
-	if(reqPath == null || !reqPath.endsWith("/")) {
-		if(reqPath == null) {
-			reqPath = "";
-		}
-		String redirect = req.getContextPath()+reqPath+"/?viewer=default";
-		res.sendRedirect(redirect); 
-	} else {
-    	res.sendRedirect("?viewer=default");
-	}
-  }
-  
-  public void execute(HttpServletRequest req, HttpServletResponse res,
-    Collection parentCol, String resourceName) throws ServletException, IOException {
-
-    try {      
-      Object resource = parentCol.getEntry(resourceName);
-      
-      if(resource != null) {
-
-        long creationDate = 0;
-        long modificationDate = 0;
-        Record record = parentCol.getFiler().readRecord(new Key(resourceName));
-        creationDate =((Long)record.getMetaData(Record.CREATED)).longValue();
-        modificationDate =((Long)record.getMetaData(Record.MODIFIED)).longValue();
-        
-		byte[] resultBytes = null;
-        if(resource instanceof Document) {
-			resultBytes = TextWriter.toString((Document)resource).getBytes();
-			res.setContentType(MimeTableImpl.XML_MIME_TYPE);
         } else {
-        	resultBytes = (byte[]) resource;
-			try {
-				MimeTable mimeTable =
-				(MimeTable) m_serviceManager.lookup(MimeTable.ROLE);
-				res.setContentType(mimeTable.getMimeType(resourceName, false));
-			} catch (ServiceException e) {
-				e.printStackTrace();
-				res.setContentType(MimeTable.BINARY_MIME_TYPE);
-			}
+            Collection col = target.getCollection();
+            String name = target.getName();
+
+            try {
+                Entry resource = col.getEntry(name);
+
+                if (resource != null) {
+
+                    byte[] resultBytes;
+                    if (resource.getEntryType() == Entry.DOCUMENT) {
+                        resultBytes = TextWriter.toString((Document) resource.getValue()).getBytes();
+                        res.setContentType(MimeTable.XML_MIME_TYPE);
+                    } else {
+                        resultBytes = (byte[]) resource.getValue();
+                        res.setContentType(MimeTable.getMimeType(name));
+                    }
+
+                    if (resource.getModificationTime() != 0) {
+                        res.addDateHeader("Last-Modified", resource.getModificationTime());
+                    }
+                    res.setContentLength(resultBytes.length);
+
+                    OutputStream output = res.getOutputStream();
+                    output.write(resultBytes);
+                    output.flush();
+                } else {
+                    res.setStatus(HttpServletResponse.SC_NOT_FOUND);
+                }
+            } catch (DBException e) {
+                log.error("Could not get resource " + name + " from collection " + col.getCanonicalName(), e);
+                throw new ServletException(e);
+            }
+
         }
-		int contentLength = resultBytes.length;
 
-        res.addDateHeader("Last-Modified", modificationDate);
-        res.addHeader("ETag", contentLength+"-"+creationDate);
-        res.setContentLength(contentLength );
-
-        OutputStream output = res.getOutputStream();
-        output.write(resultBytes);
-        output.flush();
-      } else {
-        res.sendError(HttpServletResponse.SC_NOT_FOUND);
-      }
-    } catch(DBException e) {
-      if (this.getLogger().isDebugEnabled()) {
-        this.getLogger().debug("Could not get Document "+resourceName);
-      }
-      e.printStackTrace();
-      res.sendError(HttpServletResponse.SC_NOT_FOUND);
     }
-  }
 }

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Get.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Thu May 24 18:43:39 2007
@@ -1 +1 @@
-Author Date Id Revision
+Id Revision Author Date

Modified: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Head.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Head.java?view=diff&rev=541504&r1=541498&r2=541504
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Head.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Head.java Thu May 24 18:43:39 2007
@@ -22,88 +22,72 @@
 import java.io.IOException;
 
 import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.avalon.fortress.impl.DefaultContainer;
-import org.apache.avalon.framework.service.ServiceException;
 import org.apache.xindice.core.Collection;
 import org.apache.xindice.core.DBException;
-import org.apache.xindice.core.data.Key;
-import org.apache.xindice.core.data.Record;
+import org.apache.xindice.core.data.Entry;
 import org.apache.xindice.webadmin.util.MimeTable;
-import org.apache.xindice.webadmin.webdav.*;
+import org.apache.xindice.webadmin.webdav.DAVRequest;
+import org.apache.xindice.webadmin.webdav.DAVResponse;
+import org.apache.xindice.webadmin.Location;
+import org.apache.xindice.xml.TextWriter;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.logging.Log;
+import org.w3c.dom.Document;
 
-/** 
- * This class implements the Head command for WebDAV operations on
+/**
+ * This class implements the Head HTTP command for WebDAV operations on
  * Xindice. 
  * 
- * @avalon.component
- * @avalon.service type=DAVComponent
- * @x-avalon.info name=HEAD
- * @x-avalon.lifestyle type=singleton
- * 
  * @author <a href="mailto:jmetzner@apache.org">Jan Metzner</a>
  * @author <a href="mailto:gianugo@apache.org">Gianugo Rabellino</a>
  * @version $Id$ 
  */
-public class Head extends DefaultContainer implements DAVComponent {
+public class Head implements DAVComponent {
+    private static final Log log = LogFactory.getLog(Head.class);
 
-    public void execute(
-        HttpServletRequest req,
-        HttpServletResponse res,
-        Collection col)
-        throws ServletException, IOException {
-
-        if (this.getLogger().isDebugEnabled())
-            this.getLogger().debug("Method Head not allowed on collections!");
-        res.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
-    }
-
-    public void execute(
-        HttpServletRequest req,
-        HttpServletResponse res,
-        Collection parentCol,
-        String resourceName)
-        throws ServletException, IOException {
+    public void execute(DAVRequest req, DAVResponse res, Location target) throws ServletException, IOException {
+        Collection col = target.getCollection();
+        String name = target.getName();
+
+        if (target.isRoot() || (col != null && name == null)) {
+            if (log.isDebugEnabled()) {
+                log.debug("Method Head not allowed on collections!");
+            }
+            res.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
+            return;
+        }
+
+        if (col == null) {
+            res.setStatus(HttpServletResponse.SC_NOT_FOUND);
+            return;
+        }
 
         try {
-            Object resource = parentCol.getEntry(resourceName);
+            Entry resource = col.getEntry(name);
 
             if (resource != null) {
-                long creationDate = 0;
-                long modificationDate = 0;
-                int contentLength = 0;
-                Record record =
-                    parentCol.getFiler().readRecord(new Key(resourceName));
-                creationDate =
-                    ((Long)record.getMetaData(Record.CREATED)).longValue();
-                modificationDate =
-                    ((Long)record.getMetaData(Record.MODIFIED)).longValue();
-                contentLength = record.getValue().getLength();
-
-                try {
-                    MimeTable mimeTable =
-                        (MimeTable)m_serviceManager.lookup(MimeTable.ROLE);
-                    res.setContentType(
-                        mimeTable.getMimeType(resource, resourceName));
-                } catch (ServiceException e) {
-                    e.printStackTrace();
+
+                byte[] resultBytes;
+                if (resource.getEntryType() == Entry.DOCUMENT) {
+                    resultBytes = TextWriter.toString((Document) resource.getValue()).getBytes();
                     res.setContentType(MimeTable.XML_MIME_TYPE);
+                } else {
+                    resultBytes = (byte[]) resource.getValue();
+                    res.setContentType(MimeTable.getMimeType(name));
                 }
-                res.addDateHeader("Last-Modified", modificationDate);
-                res.addHeader("ETag", contentLength + "-" + creationDate);
-                res.setContentLength(contentLength);
 
+                if (resource.getModificationTime() != 0) {
+                    res.addDateHeader("Last-Modified", resource.getModificationTime());
+                }
+                res.setContentLength(resultBytes.length);
             } else {
-                res.sendError(HttpServletResponse.SC_NOT_FOUND);
+                res.setStatus(HttpServletResponse.SC_NOT_FOUND);
             }
         } catch (DBException e) {
-            if (this.getLogger().isDebugEnabled())
-                this.getLogger().debug(
-                    "Could not get Document " + resourceName);
-            e.printStackTrace();
-            res.sendError(HttpServletResponse.SC_NOT_FOUND);
+            log.error("Could not get resource " + name + " from collection " + col.getCanonicalName(), e);
+            res.setStatus(HttpServletResponse.SC_NOT_FOUND);
         }
     }
 }

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Head.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Thu May 24 18:43:39 2007
@@ -1 +1 @@
-Author Date Id Revision
+Id Revision Author Date

Modified: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Mkcol.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Mkcol.java?view=diff&rev=541504&r1=541498&r2=541504
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Mkcol.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Mkcol.java Thu May 24 18:43:39 2007
@@ -22,99 +22,111 @@
 import java.io.IOException;
 
 import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 
-import org.apache.avalon.fortress.impl.DefaultContainer;
-import org.apache.avalon.framework.service.ServiceSelector;
 import org.apache.xindice.core.Collection;
 import org.apache.xindice.core.DBException;
+import org.apache.xindice.core.FaultCodes;
 import org.apache.xindice.webadmin.util.CollectionConfigurationHelper;
-import org.apache.xindice.webadmin.webdav.*;
 import org.apache.xindice.webadmin.webdav.WebdavStatus;
-import org.w3c.dom.Document;
+import org.apache.xindice.webadmin.webdav.DAVResponse;
+import org.apache.xindice.webadmin.webdav.DAVRequest;
+import org.apache.xindice.webadmin.Location;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 
-/** 
+/**
  * This class implements the Mkcol command for WebDAV operations on
- * Xindice. 
- * 
- * @avalon.component
- * @avalon.service type=DAVComponent
- * @x-avalon.info name=MKCOL
- * @x-avalon.lifestyle type=singleton
- * 
+ * Xindice.<br>
+ * <br>
+ * MKCOL command creates new collection at a specified location. There must be
+ * no existing collection at the specified location. Newly created collection
+ * will be empty. WebDAV specification allows request to have a body that may
+ * contain instructions for creating child resources, but this behavior is
+ * not suppoted. <br>
+ * <br>
+ * Operation possible status codes include: <ul>
+ * <li>
+ * 201 (Created) - The collection or structured resource was created in
+ * its entirety.
+ * <li>
+ * 403 (Forbidden) - This indicates at least one of two conditions: 1)
+ * the server does not allow the creation of collections at the given
+ * location in its namespace, or 2) the parent collection of the
+ * Request-URI exists but cannot accept members.
+ * <li>
+ * 405 (Method Not Allowed) - MKCOL can only be executed on a
+ * deleted/non-existent resource.
+ * <li>
+ * 409 (Conflict) - A collection cannot be made at the Request-URI until
+ * one or more intermediate collections have been created.
+ * <li>
+ * 415 (Unsupported Media Type)- The server does not support the request
+ * type of the body.
+ * </ul>
+ *
  * @author <a href="mailto:jmetzner@apache.org">Jan Metzner</a>
  * @author <a href="mailto:gianugo@apache.org">Gianugo Rabellino</a>
- * @version $Id $ 
+ * @version $Id $
  */
 
-public class Mkcol extends DefaultContainer implements DAVComponent {
+public class Mkcol implements DAVComponent {
+    private final Log log = LogFactory.getLog(Mkcol.class);
 
-    public void execute(
-        HttpServletRequest req,
-        HttpServletResponse res,
-        Collection col)
-        throws ServletException, IOException {
-
-        if (this.getLogger().isDebugEnabled()) {
-            this.getLogger().debug("collection already exists");
+    public void execute(DAVRequest req, DAVResponse res, Location target) throws ServletException, IOException {
+        if (target.isRoot()) {
+            res.setStatus(WebdavStatus.SC_METHOD_NOT_ALLOWED);
+            return;
         }
-        res.sendError(WebdavStatus.SC_METHOD_NOT_ALLOWED);
-    }
 
-    public void execute(
-        HttpServletRequest req,
-        HttpServletResponse res,
-        Collection parentCol,
-        String resourceName)
-        throws ServletException, IOException {
+        Collection col = target.getCollection();
+        String name = target.getName();
 
-        Document resource = null;
-        try {
-            resource = parentCol.getDocument(resourceName);
-        } catch (DBException e) {
-            resource = null;
+        if (name != null && req.getRequestDoc() != null) {
+            // request body is not supported
+            res.setStatus(WebdavStatus.SC_UNSUPPORTED_MEDIA_TYPE);
+            return;
         }
 
-        if (resource != null) {
-            if (this.getLogger().isDebugEnabled()) {
-                this.getLogger().debug(
-                    "cannot create collection: existing resource "
-                        + resourceName);
+        if (col == null) { // parent collection does not exist
+            res.setStatus(WebdavStatus.SC_CONFLICT);
+            return;
+        }
+
+        if (name == null) {
+            if (log.isDebugEnabled()) {
+                log.debug("Collection already exists");
             }
-            res.sendError(WebdavStatus.SC_METHOD_NOT_ALLOWED);
+            res.setStatus(WebdavStatus.SC_METHOD_NOT_ALLOWED);
         } else {
-
             try {
-                CollectionConfigurationHelper helper;
-                Object object =
-                    m_serviceManager.lookup(CollectionConfigurationHelper.ROLE);
-                if (object instanceof ServiceSelector) {
-                    helper =
-                        (CollectionConfigurationHelper)
-                            ((ServiceSelector)object).select(
-                            "col-config");
-                } else {
-                    helper = (CollectionConfigurationHelper)object;
-                }
-
-                parentCol.createCollection(
-                    resourceName,
-                    helper.createDefaultConfiguration(resourceName));
-                if (this.getLogger().isDebugEnabled()) {
-                    this.getLogger().debug(
-                        "collection " + resourceName + " created");
-                }
-            } catch (Exception e) {
-                if (this.getLogger().isDebugEnabled()) {
-                    this.getLogger().debug(
-                        "cannot create collection: " + e.getMessage());
-                    e.printStackTrace();
-                }
-                res.sendError(WebdavStatus.SC_METHOD_NOT_ALLOWED);
-                return;
+                res.setStatus(createCollection(col, name));
+            } catch (DBException e) {
+                log.error("Failed to create collection " + col.getCanonicalName() + "/" + name, e);
+                throw new ServletException(e);
             }
         }
-        res.setStatus(WebdavStatus.SC_CREATED);
+    }
+
+    private int createCollection(Collection parent, String name) throws DBException {
+        try {
+            parent.createCollection(name, CollectionConfigurationHelper.createDefaultConfiguration(name));
+            if (log.isDebugEnabled()) {
+                log.debug("Collection " + name + " created");
+            }
+
+            // TODO: set SC_FORBIDDEN for system collections
+        } catch (DBException e) {
+            if (e.faultCode == FaultCodes.COL_DUPLICATE_COLLECTION) {
+                return WebdavStatus.SC_METHOD_NOT_ALLOWED;
+            } else if (e.faultCode == FaultCodes.COL_COLLECTION_NOT_FOUND) {
+                return WebdavStatus.SC_METHOD_NOT_ALLOWED;
+            } else if (e.faultCode == FaultCodes.COL_CANNOT_CREATE) {
+                return WebdavStatus.SC_FORBIDDEN;
+            }
+
+            throw e;
+        }
+
+        return WebdavStatus.SC_CREATED;
     }
 }

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Mkcol.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Thu May 24 18:43:39 2007
@@ -1 +1 @@
-Author Date Id Revision
+Id Revision Author Date

Modified: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Move.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Move.java?view=diff&rev=541504&r1=541498&r2=541504
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Move.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Move.java Thu May 24 18:43:39 2007
@@ -20,108 +20,149 @@
 package org.apache.xindice.webadmin.webdav.components;
 
 import java.io.IOException;
+import java.util.Map;
+import java.util.Iterator;
 
 import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 
-import org.apache.avalon.fortress.impl.DefaultContainer;
-import org.apache.avalon.framework.service.ServiceSelector;
 import org.apache.xindice.core.Collection;
 import org.apache.xindice.core.DBException;
+import org.apache.xindice.core.FaultCodes;
 import org.apache.xindice.webadmin.util.DAVOperations;
-import org.apache.xindice.webadmin.webdav.*;
 import org.apache.xindice.webadmin.webdav.WebdavStatus;
+import org.apache.xindice.webadmin.webdav.DAVRequest;
+import org.apache.xindice.webadmin.webdav.DAVResponse;
+import org.apache.xindice.webadmin.PartialResponse;
+import org.apache.xindice.webadmin.Location;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 
-/** 
+/**
  * This class implements the Move command for WebDAV operations on
- * Xindice. 
- * 
- * @avalon.component
- * @avalon.service type=DAVComponent
- * @x-avalon.info name=MOVE
- * @x-avalon.lifestyle type=singleton
- * 
+ * Xindice.<br>
+ * <br>
+ * MOVE commans instructs that the collection or resource be moved to the
+ * URI specified in the Destination header. In case of collection, all
+ * resources and child collections are to be moved to locations relative
+ * to it, recursively through all levels of the collection hierarchy.<br>
+ * <br>
+ * MOVE can overwrite existing resource/collection, and this behavior can
+ * be changed by using Overwrite flag in request header.<br>
+ * <br>
+ * For collections, Depth header cannot have any value other than infinity.<br>
+ * <br>
+ * Operation possible status codes include: <ul>
+ * <li>
+ * 201 (Created) - The source resource was successfully moved, and a new
+ * resource was created at the destination.
+ *
+ * 204 (No Content) - The source resource was successfully moved to a
+ * pre-existing destination resource.
+ *
+ * 403 (Forbidden) _ The source and destination URIs are the same.
+ *
+ * 409 (Conflict) _ A resource cannot be created at the destination
+ * until one or more intermediate collections have been created.
+ *
+ * 412 (Precondition Failed) - The server was unable to maintain the
+ * liveness of the properties listed in the propertybehavior XML element
+ * or the Overwrite header is "F" and the state of the destination
+ * resource is non-null.
+ *
  * @author <a href="mailto:jmetzner@apache.org">Jan Metzner</a>
  * @author <a href="mailto:gianugo@apache.org">Gianugo Rabellino</a>
- * @version $Id$ 
+ * @version $Id$
  */
 
-public class Move extends DefaultContainer implements DAVComponent {
+public class Move implements DAVComponent {
+    private static final Log log = LogFactory.getLog(Move.class);
 
-    public void execute(
-        HttpServletRequest req,
-        HttpServletResponse res,
-        Collection col)
-        throws ServletException, IOException {
-
-        int status = WebdavStatus.SC_OK;
-        try {
-            DAVOperations davOps;
-            Object object = m_serviceManager.lookup(DAVOperations.ROLE);
-            if (object instanceof ServiceSelector) {
-                davOps =
-                    (DAVOperations) ((ServiceSelector)object).select(
-                        "dav-operations");
-            } else {
-                davOps = (DAVOperations)object;
-            }
+    public void execute(DAVRequest req, DAVResponse res, Location target) throws ServletException, IOException {
+        if (target.isRoot()) {
+            res.setStatus(WebdavStatus.SC_FORBIDDEN);
+            return;
+        }
 
-            status = davOps.copy(req, col.getParentCollection(), col.getName());
-            if (status == WebdavStatus.SC_NO_CONTENT
-                || status == WebdavStatus.SC_CREATED) {
-                Collection parentCol = col.getParentCollection();
-                parentCol.dropCollection(col);
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-            throw new ServletException(e);
+        Collection col = target.getCollection();
+        String name = target.getName();
+
+        if (col == null) {
+            res.setStatus(WebdavStatus.SC_NOT_FOUND);
+            return;
         }
-        res.setStatus(status);
-    }
 
-    public void execute(
-        HttpServletRequest req,
-        HttpServletResponse res,
-        Collection parentCol,
-        String resourceName)
-        throws ServletException, IOException {
-
-        Object object = null;
-        try {
-            object = parentCol.getEntry(resourceName);
-        } catch (DBException e) {
-            if (this.getLogger().isDebugEnabled()) {
-                this.getLogger().debug(
-                    "could not get document " + resourceName);
-            }
-            object = null;
+        String dest = req.getDestinationPath();
+        if (dest == null) {
+            res.setStatus(WebdavStatus.SC_BAD_REQUEST);
+            return;
         }
 
-        if (object == null) {
-            res.setStatus(WebdavStatus.SC_NOT_FOUND);
-        } else {
+        if (dest.equals(req.getPath())) {
+            res.setStatus(WebdavStatus.SC_FORBIDDEN);
+            return;
+        }
+
+        int depth = req.getDepth();
+        if (depth != DAVRequest.DEPTH_INFINITY) {
+            res.setStatus(WebdavStatus.SC_BAD_REQUEST);
+            return;
+        }
+
+        if (name == null) { // moving collection
             try {
-                DAVOperations davOps;
-                Object service = m_serviceManager.lookup(DAVOperations.ROLE);
-                if (service instanceof ServiceSelector) {
-                    davOps =
-                        (DAVOperations) ((ServiceSelector)service).select(
-                            "dav-operations");
-                } else {
-                    davOps = (DAVOperations)service;
+                Map results = DAVOperations.copy(col, req.getDestinationPath(), req.getOverwrite(), true);
+                interpretResults(results, res, dest, col);
+            } catch (DBException e) {
+                log.error("Failed to move collection " + col.getCanonicalName(), e);
+                throw new ServletException(e);
+            }
+        } else { // moving resource
+            try {
+                int status = DAVOperations.copy(col, name, req.getDestinationPath(), req.getOverwrite());
+                if (status == WebdavStatus.SC_NO_CONTENT || status == WebdavStatus.SC_CREATED) {
+                    col.remove(name);
                 }
+                res.setStatus(status);
+            } catch (DBException e) {
+                log.error("Failed to move resource " + name + " from collection " + col.getCanonicalName(), e);
+                throw new ServletException(e);
+            }
+        }
+    }
 
-                int status = davOps.copy(req, parentCol, resourceName);
-                if (status == WebdavStatus.SC_NO_CONTENT
-                    || status == WebdavStatus.SC_CREATED) {
-                    parentCol.remove(resourceName);
+    private void interpretResults(Map results, DAVResponse res, String dest, Collection col) throws IOException {
+        for (Iterator i = results.keySet().iterator(); i.hasNext(); ) {
+            String url = (String) i.next();
+            int status = ((Integer) results.get(url)).intValue();
+            if (url.equals(dest)) {
+                if (status == WebdavStatus.SC_CREATED || status == WebdavStatus.SC_NO_CONTENT) {
+                    try {
+                        col.getDatabase().dropCollection(col);
+                    } catch (DBException e) {
+                        if (e.faultCode == FaultCodes.COL_CANNOT_DROP) {
+                            // cannot drop database
+                            status = WebdavStatus.SC_FORBIDDEN;
+                        } else if (e.faultCode != FaultCodes.COL_COLLECTION_NOT_FOUND) {
+                            status = WebdavStatus.SC_INTERNAL_SERVER_ERROR;
+                        }
+                    }
                 }
+
                 res.setStatus(status);
-            } catch (Exception e) {
-                throw new ServletException(e);
+                return;
             }
+
+            /*
+             * If an error in executing the MOVE method occurs with a resource other
+             * than the resource identified in the Request-URI then the response
+             * MUST be a 207 (Multi-Status).
+             */
+            PartialResponse part = new PartialResponse(dest);
+            String st = res.getProtocol() + " " + status + " " + WebdavStatus.getStatusText(status);
+            part.addContent("status", st);
+            res.sendMultiStatusResponse(part);
         }
 
+        res.closeMultistatusResponse();
     }
 }

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/webdav/components/Move.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Thu May 24 18:43:39 2007
@@ -1 +1 @@
-Author Date Id Revision
+Id Revision Author Date