juergen 02/05/07 06:07:19
Modified: src/webdav/server/org/apache/slide/webdav/method
UpdateMethod.java
Log:
Implemented additional semantics for LABEL feature.
Implement multistatus response with requested properties.
(ralf)
Revision Changes Path
1.2 +299 -28
jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/UpdateMethod.java
Index: UpdateMethod.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/UpdateMethod.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- UpdateMethod.java 1 May 2002 15:04:35 -0000 1.1
+++ UpdateMethod.java 7 May 2002 13:07:19 -0000 1.2
@@ -1,7 +1,7 @@
/*
- * $Header:
/home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/UpdateMethod.java,v
1.1 2002/05/01 15:04:35 pnever Exp $
- * $Revision: 1.1 $
- * $Date: 2002/05/01 15:04:35 $
+ * $Header:
/home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/UpdateMethod.java,v
1.2 2002/05/07 13:07:19 juergen Exp $
+ * $Revision: 1.2 $
+ * $Date: 2002/05/07 13:07:19 $
*
* ====================================================================
*
@@ -82,7 +82,9 @@
import org.apache.slide.common.NamespaceAccessToken;
import org.apache.slide.common.RequestedProperties;
import org.apache.slide.common.RequestedPropertiesImpl;
+import org.apache.slide.common.SlideException;
import org.apache.slide.structure.SubjectNode;
+import org.apache.slide.structure.ObjectNode;
import org.apache.slide.content.NodeProperty;
import org.apache.slide.content.NodeRevisionContent;
import org.apache.slide.content.NodeRevisionDescriptor;
@@ -90,11 +92,22 @@
import org.apache.slide.content.NodeRevisionNumber;
import org.apache.slide.webdav.WebdavServletConfig;
import org.apache.slide.webdav.WebdavException;
+
+import org.apache.slide.webdav.util.AbstractWebdavHelper;
import org.apache.slide.webdav.util.VersioningHelper;
import org.apache.slide.webdav.util.UriHandler;
import org.apache.slide.webdav.util.DeltavConstants;
import org.apache.slide.webdav.util.ViolatedPrecondition;
+import org.apache.slide.webdav.util.PropertyHelper;
+import org.apache.slide.webdav.util.PropertyRetriever;
+import org.apache.slide.webdav.util.PropertyRetrieverImpl;
+import org.apache.slide.webdav.util.LabeledRevisionNotFoundException;
import org.apache.slide.webdav.util.PreconditionViolationException;
+
+import org.apache.slide.webdav.util.resourcekind.AbstractResourceKind;
+import org.apache.slide.webdav.util.resourcekind.ResourceKind;
+import org.apache.slide.webdav.util.resourcekind.CheckedInVersionControlled;
+
import org.apache.util.WebdavStatus;
/**
@@ -111,9 +124,27 @@
/** The update source */
private String updateSourcePath;
+ /** The label of the update source */
+ private String updateLabelName;
+
/** Requested properties */
private RequestedProperties requestedProps;
+ /**
+ * The VersioningHelper used by this instance.
+ */
+ protected VersioningHelper versioningHelper = null;
+
+ /**
+ * The URI of the server, e.g. <code>localhost:4000</code>.
+ */
+ protected String serverUri = null;
+
+ /**
+ * The PropertyRetriever used to retrieve any requested properties.
+ */
+ protected PropertyRetriever propertyRetriever = null;
+
/**
* UPDATE method constructor.
@@ -128,7 +159,11 @@
WebdavServletConfig config)
{
super(token, req, resp, config);
+ versioningHelper = VersioningHelper.getVersioningHelper(
+ slideToken, token, req, resp, getConfig() );
readRequestContent();
+ serverUri = req.getServerName() + ":" + req.getServerPort();
+ propertyRetriever = new PropertyRetrieverImpl(token, slideToken);
}
/**
@@ -137,24 +172,48 @@
* @exception WebdavException
*/
protected void parseRequest() throws WebdavException, IOException {
+
resourcePath = requestUri;
if (resourcePath == null) {
resourcePath = "/";
}
if( req.getContentLength() == 0 ) {
- Domain.warn( "Request body required" );
- resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
+ resp.sendError(WebdavStatus.SC_BAD_REQUEST, "Request body required");
throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
}
try{
retrieveRequestContent();
+ parseUpdateRequestContent();
+ }
+ catch( org.xml.sax.SAXException x ){
+ resp.sendError(WebdavStatus.SC_BAD_REQUEST, x.getMessage());
+ throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
+ }
+ catch( IOException x ){
+ resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
+ throw new WebdavException(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
+ }
+ catch( javax.xml.parsers.ParserConfigurationException x ){
+ resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
+ throw new WebdavException(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ /**
+ * Parses the expected request content specified for the Update method.
+ *
+ * @throws WebdavException
+ * @throws IOException
+ */
+ private void parseUpdateRequestContent() throws WebdavException, IOException {
+
Element ue = getRequestContent().getRootElement();
Element ve = null;
if( ue == null || !ue.getName().equals(E_UPDATE) ) {
- Domain.warn( "Root element must be "+E_UPDATE );
- resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
+ resp.sendError(WebdavStatus.SC_BAD_REQUEST,
+ "Root element must be <"+E_UPDATE+">");
throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
}
Iterator i = ue.getChildren().iterator();
@@ -162,8 +221,13 @@
Element e = (Element)i.next();
if( e.getName().equals(E_VERSION) ) {
if( updateSourcePath != null ) {
- Domain.warn( "At most one "+E_VERSION+" element allowed" );
- resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
+ resp.sendError(WebdavStatus.SC_BAD_REQUEST,
+ "At most one <"+E_VERSION+"> element
allowed" );
+ throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
+ }
+ if (updateLabelName != null) {
+ resp.sendError(WebdavStatus.SC_BAD_REQUEST,
+ "Either a <"+E_VERSION+"> OR a
<"+E_LABEL_NAME+"> element allowed");
throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
}
// get the href element
@@ -175,32 +239,32 @@
updateSourcePath = getSlidePath( hre.getText() );
}
catch( Exception x ) {
- Domain.warn( E_VERSION+" element must contain "+E_HREF+"
element" );
- resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
+ resp.sendError(WebdavStatus.SC_BAD_REQUEST,
+ "<"+E_VERSION+"> element must contain
<"+E_HREF+"> element" );
throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
}
}
if( e.getName().equals(E_PROP) ) {
if( requestedProps != null ) {
- Domain.warn( "At most one "+E_PROP+" element allowed" );
- resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
+ resp.sendError(WebdavStatus.SC_BAD_REQUEST,
+ "At most one "+E_PROP+" element allowed" );
throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
}
requestedProps = new RequestedPropertiesImpl( e );
}
+ if( e.getName().equals(E_LABEL_NAME) ) {
+ if (updateSourcePath != null) {
+ resp.sendError(WebdavStatus.SC_BAD_REQUEST,
+ "Either a <"+E_VERSION+"> OR a
<"+E_LABEL_NAME+"> element allowed");
+ throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
}
- }
- catch( org.xml.sax.SAXException x ){
- resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
+ if( updateLabelName != null ) {
+ resp.sendError(WebdavStatus.SC_BAD_REQUEST,
+ "At most one <"+E_LABEL_NAME+"> element
allowed" );
throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
}
- catch( IOException x ){
- resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
- throw new WebdavException(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
+ updateLabelName = e.getText();
}
- catch( javax.xml.parsers.ParserConfigurationException x ){
- resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
- throw new WebdavException(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
}
}
@@ -215,21 +279,228 @@
slideToken.setForceStoreEnlistment(true);
try {
- VersioningHelper vh = VersioningHelper.getVersioningHelper(
- slideToken, token, req, resp, getConfig() );
- vh.update( resourcePath, updateSourcePath );
- }
- catch (PreconditionViolationException e) {
- sendPreconditionViolation(e);
- throw e;
+ Element multistatusElement = new Element(E_MULTISTATUS,
+
Namespace.getNamespace(DEFAULT_NAMESPACE));
+
+ update(updateSourcePath, updateLabelName, resourcePath, getDepth(),
multistatusElement);
+
+ resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
+ resp.setContentType(TEXT_XML_UTF_8);
+ new XMLOutputter().output(multistatusElement, resp.getWriter());
}
catch (Exception e) {
e.printStackTrace();
resp.setStatus( getErrorCode(e) ); // special handling needed
throw new WebdavException( WebdavStatus.SC_ACCEPTED, false ); // abort
the TA
}
+ }
+
+ /**
+ * Updates the resource identified by <code>resourcePath</code>
+ * with the properties and the content either of the resource identified
+ * <code>updateSourcePath</code> or the version with the label
+ * <code>updateLabelName</code> (only one of these parameters is set).
+ * If <code>depth</code> is > 0, the operation is applied recursivly
+ * to all children of the destination resource.
+ *
+ * @param updateSourcePath the URI of update source.
+ * @param updateLabelName the label of the version used for the update.
+ * @param resourcePath the URI of update destination.
+ * @param depth the depth to use. If > 0, the update is
+ * applied recursivly.
+ * @param multistatusElement the <code><multistatus></code> element
+ * to append the <code><response></code>
+ * elements to.
+ */
+ protected void update(String updateSourcePath, String updateLabelName, String
resourcePath, int depth, Element multistatusElement) {
+
+ Element responseElement = new Element(E_RESPONSE,
Namespace.getNamespace(DEFAULT_NAMESPACE));
+ multistatusElement.addContent(responseElement);
+ Element hrefElement = new Element(E_HREF,
Namespace.getNamespace(DEFAULT_NAMESPACE));
+ hrefElement.setText(PropertyHelper.getAbsoluteURL(serverUri,
req.getContextPath(), resourcePath));
+ responseElement.addContent(hrefElement);
+ Element statusElement = new Element(E_STATUS,
Namespace.getNamespace(DEFAULT_NAMESPACE));
+ responseElement.addContent(statusElement);
+
+ Enumeration childrenEnum = null;
+ try {
+ if ( isCollection(resourcePath) && (depth > 0) ) {
+ ObjectNode currentNode = structure.retrieve(slideToken,
resourcePath);
+ childrenEnum = structure.getChildren(slideToken, currentNode);
+ }
+
+ checkPreconditions(updateSourcePath, updateLabelName, resourcePath);
+
+ if (updateLabelName != null) {
+ updateSourcePath =
versioningHelper.getLabeledResourceUri(resourcePath,
+
updateLabelName);
+ }
+
+ versioningHelper.update( resourcePath, updateSourcePath );
+ statusElement.setText(HTTP_VERSION + " " +
+ WebdavStatus.SC_OK + " " +
+
WebdavStatus.getStatusText(WebdavStatus.SC_OK));
+
+ appendRequestedProps(resourcePath, responseElement);
+ }
+ catch (Exception e) {
+ handleException(e, statusElement, responseElement);
+ }
+ // process children recursivly
+ if (childrenEnum != null) {
+ while (childrenEnum.hasMoreElements()) {
+ update(updateSourcePath,
+ updateLabelName,
+ ((ObjectNode)childrenEnum.nextElement()).getUri(),
+ depth-1,
+ multistatusElement);
+ }
+ }
}
+
+ /**
+ * Appends the <propstat> elements for the requested properties to
+ * the given <code>responseElement</code>.
+ *
+ * @param resourcePath the path of the resource for which to retrieve
+ * the properties.
+ * @param responseElement the <reponse> element to add the
<propstat>
+ * elements to.
+ *
+ * @throws SlideException
+ * @throws JDOMException
+ */
+ private void appendRequestedProps(String resourcePath, Element responseElement)
throws SlideException, JDOMException {
+
+ if (requestedProps != null) {
+ List propStatList =
propertyRetriever.getPropertiesOfObject(requestedProps,
+
resourcePath,
+
req.getContextPath(),
+ serverUri,
+ true);
+ Iterator iterator = propStatList.iterator();
+ while (iterator.hasNext()) {
+ responseElement.addContent((Element)iterator.next());
+ }
+ }
+ }
+
+
+ /**
+ * Checks the preconditions of the Update method.
+ *
+ * @param updateSourcePath the URI of update source.
+ * @param updateLabelName the label of the version used for the update.
+ * @param resourcePath the URI of update destination.
+ *
+ * @throws SlideException
+ * @throws PreconditionViolationException if any precondition has been
violated.
+ */
+ private void checkPreconditions(String updateSourcePath, String
updateLabelName, String resourcePath) throws SlideException,
PreconditionViolationException {
+
+ ViolatedPrecondition violatedPrecondition =
getPreconditionViolation(updateSourcePath,
+
updateLabelName,
+
resourcePath);
+ if (violatedPrecondition != null) {
+ throw new PreconditionViolationException(violatedPrecondition,
resourcePath);
+ }
+ }
+
+
+ /**
+ * Sets the appropriate status text and appends a <responsedescription>
+ * element if a precondition has been violated.
+ *
+ * @param exception the Exception that occurred.
+ * @param statusElement the <status> element.
+ * @param responseElement the <response> element.
+ */
+ private void handleException(Exception exception, Element statusElement,
Element responseElement) {
+
+ int errorCode = getErrorCode(exception);
+ statusElement.setText(HTTP_VERSION + " " + errorCode + " " +
+ WebdavStatus.getStatusText(errorCode));
+ if (exception instanceof PreconditionViolationException) {
+ Element responseDescriptionElement = new Element(E_RESPONSEDESCRIPTION,
+
Namespace.getNamespace(DEFAULT_NAMESPACE));
+ responseElement.addContent(responseDescriptionElement);
+ Element errorElement =
getPreconditionViolationError(((PreconditionViolationException)exception).getViolatedPrecondition());
+ responseDescriptionElement.addContent(errorElement);
+ }
+ }
+
+
+ /**
+ * Checks the (DeltaV) preconditions
+ * <ul>
+ * <li><DAV:must-be-checked-in-version-controlled-resource></li>
+ * <li><DAV:must-select-version-in-history></li>
+ * </ul>
+ *
+ * @param updateSourcePath the URI of update source.
+ * @param updateLabelName the label of the version used for the update.
+ * @param resourcePath the URI of update destination.
+ *
+ * @return the precondition that has been violated (if any).
+ *
+ * @throws SlideException
+ */
+ protected ViolatedPrecondition getPreconditionViolation(String
updateSourcePath, String updateSourceLabel, String resourcePath) throws SlideException
{
+
+ ViolatedPrecondition violatedPrecondition = null;
+
+ NodeRevisionDescriptors revisionDescriptors =
+ versioningHelper.retrieveRevisionDescriptors(resourcePath);
+ NodeRevisionDescriptor revisionDescriptor =
+ versioningHelper.retrieveLatestRevisionDescriptor(resourcePath,
revisionDescriptors);
+ ResourceKind resourceKind =
AbstractResourceKind.determineResourceKind(token,
+
revisionDescriptors,
+
revisionDescriptor);
+ if ( ! (resourceKind instanceof CheckedInVersionControlled) ) {
+ return new
ViolatedPrecondition(DeltavConstants.C_MUST_BE_CHECKED_IN_VERSION_CONTROLLED_RESOURCE,
+ WebdavStatus.SC_CONFLICT);
+ }
+
+ if (updateSourceLabel != null) {
+ try {
+ updateSourcePath =
versioningHelper.getLabeledResourceUri(resourcePath, updateLabelName);
+ }
+ catch (LabeledRevisionNotFoundException e) {
+ return new
ViolatedPrecondition(DeltavConstants.C_MUST_SELECT_VERSION_IN_HISTORY,
+ WebdavStatus.SC_CONFLICT);
+ }
+ }
+
+ String associatedVrUri =
versioningHelper.getUriOfAssociatedVR(resourcePath);
+ String vcrHistoryUri = UriHandler.getUriHandler(token,
associatedVrUri).getAssociatedHistoryUri();
+ String vrHistoryUri = UriHandler.getUriHandler(token,
updateSourcePath).getAssociatedHistoryUri();
+ if ( ! vcrHistoryUri.equals(vrHistoryUri) ) {
+ return new
ViolatedPrecondition(DeltavConstants.C_MUST_SELECT_VERSION_IN_HISTORY,
+ WebdavStatus.SC_CONFLICT);
+ }
+
+ return violatedPrecondition;
+ }
+
+
+ /**
+ * Returns the value of the <code>Depth</code> header. If not specified,
+ * <code>0</code> is used as default.
+ *
+ * @return the value of the <code>Depth</code> header.
+ */
+ protected int getDepth() {
+
+ int depth = 0;
+ try {
+ depth = Integer.parseInt(req.getHeader(H_DEPTH));
+ }
+ catch (NumberFormatException e) {}
+ return depth;
+ }
+
+
}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>