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><xupdate:modifications version=\"1.0\" \n" +
+ " xmlns:xupdate=\"http://www.xmldb.org/xupdate\"> \n\n" +
+ " <xupdate:insert-after select=\"/addresses/address[1]\" > \n" +
+ " <xupdate:element name=\"address\"> \n" +
+ " <xupdate:attribute name=\"id\">2</xupdate:attribute> \n" +
+ " <fullname>John Smith</fullname> \n" +
+ " <born day='2' month='12' year='1974'/> \n" +
+ " <country>Germany</country> \n" +
+ " </xupdate:element> \n\n" +
+ " </xupdate:insert-after> \n" +
+ "</xupdate:modifications> \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><xupdate:modifications version=\"1.0\" \n" +
- " xmlns:xupdate=\"http://www.xmldb.org/xupdate\"> \n\n" +
- " <xupdate:insert-after select=\"/addresses/address[1]\" > \n" +
- " <xupdate:element name=\"address\"> \n" +
- " <xupdate:attribute name=\"id\">2</xupdate:attribute> \n" +
- " <fullname>John Smith</fullname> \n" +
- " <born day='2' month='12' year='1974'/> \n" +
- " <country>Germany</country> \n" +
- " </xupdate:element> \n\n" +
- " </xupdate:insert-after> \n" +
- "</xupdate:modifications> \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