1 23 24 package org.apache.slide.webdav.method; 25 26 import java.io.IOException ; 27 import java.util.Enumeration ; 28 import java.util.Iterator ; 29 import java.util.List ; 30 31 import org.apache.slide.common.NamespaceAccessToken; 32 import org.apache.slide.common.NestedSlideException; 33 import org.apache.slide.common.PropertyParseException; 34 import org.apache.slide.common.RequestedProperties; 35 import org.apache.slide.common.RequestedPropertiesImpl; 36 import org.apache.slide.common.ServiceAccessException; 37 import org.apache.slide.common.SlideException; 38 import org.apache.slide.content.NodeRevisionDescriptor; 39 import org.apache.slide.content.NodeRevisionDescriptors; 40 import org.apache.slide.content.RevisionDescriptorNotFoundException; 41 import org.apache.slide.event.EventDispatcher; 42 import org.apache.slide.structure.ObjectNode; 43 import org.apache.slide.webdav.WebdavException; 44 import org.apache.slide.webdav.WebdavServletConfig; 45 import org.apache.slide.webdav.event.WebdavEvent; 46 import org.apache.slide.webdav.util.DeltavConstants; 47 import org.apache.slide.webdav.util.LabeledRevisionNotFoundException; 48 import org.apache.slide.webdav.util.PreconditionViolationException; 49 import org.apache.slide.webdav.util.PropertyRetriever; 50 import org.apache.slide.webdav.util.PropertyRetrieverImpl; 51 import org.apache.slide.webdav.util.UriHandler; 52 import org.apache.slide.webdav.util.VersioningHelper; 53 import org.apache.slide.webdav.util.ViolatedPrecondition; 54 import org.apache.slide.webdav.util.WebdavStatus; 55 import org.apache.slide.webdav.util.WebdavUtils; 56 import org.apache.slide.webdav.util.resourcekind.AbstractResourceKind; 57 import org.apache.slide.webdav.util.resourcekind.CheckedInVersionControlled; 58 import org.apache.slide.webdav.util.resourcekind.ResourceKind; 59 import org.jdom.Document; 60 import org.jdom.Element; 61 import org.jdom.JDOMException; 62 import org.jdom.output.XMLOutputter; 63 64 68 public class UpdateMethod extends AbstractMultistatusResponseMethod 69 implements DeltavConstants, WriteMethod { 70 71 72 private String resourcePath; 73 74 75 private String updateSourcePath; 76 77 78 private String updateLabelName; 79 80 81 private RequestedProperties requestedProps; 82 83 86 protected VersioningHelper versioningHelper = null; 87 88 91 protected String serverUri = null; 92 93 96 protected PropertyRetriever propertyRetriever = null; 97 98 99 101 102 108 public UpdateMethod(NamespaceAccessToken token, 109 WebdavServletConfig config) { 110 super(token, config); 111 } 112 113 118 protected void parseRequest() throws WebdavException { 119 120 versioningHelper = VersioningHelper.getVersioningHelper( 121 slideToken, token, req, resp, getConfig() ); 122 serverUri = req.getServerName() + ":" + req.getServerPort(); 124 propertyRetriever = new PropertyRetrieverImpl(token, slideToken, getConfig()); 125 126 resourcePath = requestUri; 127 if (resourcePath == null) { 128 resourcePath = "/"; 129 } 130 131 if( req.getContentLength() == 0 ) { 132 int statusCode = WebdavStatus.SC_BAD_REQUEST; 133 sendError( statusCode, getClass().getName()+".missingRequestBody" ); 134 throw new WebdavException( statusCode ); 135 } 136 137 try{ 138 parseUpdateRequestContent(); 139 } 140 catch (JDOMException e){ 141 int statusCode = WebdavStatus.SC_BAD_REQUEST; 142 sendError( statusCode, e ); 143 throw new WebdavException( statusCode ); 144 } 145 catch (PropertyParseException e){ 146 int statusCode = WebdavStatus.SC_BAD_REQUEST; 147 sendError( statusCode, e ); 148 throw new WebdavException( statusCode ); 149 } 150 catch( IOException e ){ 151 int statusCode = WebdavStatus.SC_INTERNAL_SERVER_ERROR; 152 sendError( statusCode, e ); 153 throw new WebdavException( statusCode ); 154 } 155 } 156 157 164 private void parseUpdateRequestContent() throws IOException , JDOMException, PropertyParseException { 165 166 Element ve = null; 167 Iterator i = parseRequestContent(E_UPDATE).getChildren().iterator(); 168 while( i.hasNext() ) { 169 Element e = (Element)i.next(); 170 if( e.getName().equals(E_VERSION) ) { 171 if( updateSourcePath != null ) { 172 throw new JDOMException("At most one <"+E_VERSION+"> element allowed" ); 173 } 174 if (updateLabelName != null) { 175 throw new JDOMException("Either a <"+E_VERSION+"> OR a <"+E_LABEL_NAME+"> element allowed"); 176 } 177 ve = e; 179 try { 180 Element hre = (Element)ve.getChildren().get(0); 181 if( hre == null || !hre.getName().equals(E_HREF) ) 182 throw new Exception (); 183 updateSourcePath = getSlidePath( hre.getText() ); 184 } 185 catch( Exception x ) { 186 throw new JDOMException("<"+E_VERSION+"> element must contain <"+E_HREF+"> element" ); 187 } 188 } 189 if( e.getName().equals(E_PROP) ) { 190 if( requestedProps != null ) { 191 throw new JDOMException("At most one "+E_PROP+" element allowed" ); 192 } 193 requestedProps = new RequestedPropertiesImpl( e ); 194 } 195 if( e.getName().equals(E_LABEL_NAME) ) { 196 if (updateSourcePath != null) { 197 throw new JDOMException("Either a <"+E_VERSION+"> OR a <"+E_LABEL_NAME+"> element allowed"); 198 } 199 if( updateLabelName != null ) { 200 throw new JDOMException("At most one <"+E_LABEL_NAME+"> element allowed" ); 201 } 202 updateLabelName = e.getText(); 203 } 204 } 205 } 206 207 212 protected void executeRequest() throws WebdavException, IOException { 213 214 slideToken.setForceStoreEnlistment(true); 216 217 try { 219 if (isLockNull(resourcePath)) { 220 int statusCode = WebdavStatus.SC_NOT_FOUND; 221 sendError( statusCode, "lock-null resource", new Object []{resourcePath} ); 222 throw new WebdavException( statusCode ); 223 } 224 } 225 catch (ServiceAccessException e) { 226 int statusCode = getErrorCode((Exception )e); 227 sendError( statusCode, e ); 228 throw new WebdavException( statusCode ); 229 } 230 231 Element multistatusElement = new Element(E_MULTISTATUS, DNSP); 232 233 try { 234 if ( WebdavEvent.UPDATE.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(WebdavEvent.UPDATE, new WebdavEvent(this)); 235 236 update(updateSourcePath, updateLabelName, resourcePath, getDepth(), multistatusElement); 237 } catch (NestedSlideException nestedSlideException) { 238 239 if (!requestHeaders.isDefined(H_DEPTH)) { 240 SlideException exception = (SlideException)nestedSlideException.enumerateExceptions().nextElement(); 242 resp.setStatus(getErrorCode(exception)); if (exception instanceof PreconditionViolationException) { 244 try { 245 sendPreconditionViolation((PreconditionViolationException)exception); 246 } catch(IOException e) { 247 int statusCode = WebdavStatus.SC_INTERNAL_SERVER_ERROR; 249 sendError( statusCode, e ); 250 throw new WebdavException( statusCode ); 251 } 252 } 253 throw new WebdavException(getErrorCode(exception), false); } 255 } catch (SlideException e) { 256 int statusCode = getErrorCode( e ); 257 sendError( statusCode, e ); 258 throw new WebdavException( statusCode ); 259 } 260 261 262 try { 263 resp.setStatus(WebdavStatus.SC_MULTI_STATUS); 264 resp.setContentType(TEXT_XML_UTF_8); 265 org.jdom.output.Format format = org.jdom.output.Format.getPrettyFormat(); 266 format.setIndent(XML_RESPONSE_INDENT); 267 new XMLOutputter(format). 268 output(new Document(multistatusElement), resp.getWriter()); 269 } 270 catch (Exception e) { 271 int statusCode = getErrorCode( e ); 272 sendError( statusCode, e ); 273 throw new WebdavException( statusCode ); 274 } 275 } 276 277 294 protected void update(String updateSourcePath, String updateLabelName, String resourcePath, int depth, Element multistatusElement) throws NestedSlideException { 295 NestedSlideException nestedSlideException = new NestedSlideException(null); 296 update(updateSourcePath, updateLabelName, resourcePath, depth, multistatusElement, nestedSlideException); 297 if ( ! nestedSlideException.isEmpty() ) { 298 throw nestedSlideException; 299 } 300 } 301 302 303 320 protected void update(String updateSourcePath, String updateLabelName, String resourcePath, int depth, Element multistatusElement, NestedSlideException nestedSlideException) { 321 322 Element responseElement = new Element(E_RESPONSE, DNSP); 323 multistatusElement.addContent(responseElement); 324 Element hrefElement = new Element(E_HREF, DNSP); 325 326 String absUri = WebdavUtils.getAbsolutePath (resourcePath, req, getConfig()); 327 hrefElement.setText(absUri); 328 responseElement.addContent(hrefElement); 329 330 Element statusElement = new Element(E_STATUS, DNSP); 331 responseElement.addContent(statusElement); 332 333 Enumeration childrenEnum = null; 334 try { 335 if ( isCollection(resourcePath) && (depth > 0) ) { 336 ObjectNode currentNode = structure.retrieve(slideToken, resourcePath); 337 childrenEnum = structure.getChildren(slideToken, currentNode); 338 } 339 340 checkPreconditions(updateSourcePath, updateLabelName, resourcePath); 341 342 if (updateLabelName != null) { 343 updateSourcePath = versioningHelper.getLabeledResourceUri(resourcePath, 344 updateLabelName); 345 } 346 347 versioningHelper.update( resourcePath, updateSourcePath ); 348 statusElement.setText(HTTP_VERSION + " " + 349 WebdavStatus.SC_OK + " " + 350 WebdavStatus.getStatusText(WebdavStatus.SC_OK)); 351 352 appendRequestedProps(resourcePath, responseElement); 353 } 354 catch (SlideException e) { 355 handleException(e, statusElement, responseElement, nestedSlideException); 356 } 357 catch (JDOMException e) { 358 handleException(e, statusElement, responseElement, nestedSlideException); 359 } 360 if (childrenEnum != null) { 362 while (childrenEnum.hasMoreElements()) { 363 update(updateSourcePath, 364 updateLabelName, 365 ((ObjectNode)childrenEnum.nextElement()).getUri(), 366 depth-1, 367 multistatusElement, 368 nestedSlideException); 369 } 370 } 371 } 372 373 385 private void appendRequestedProps(String resourcePath, Element responseElement) throws SlideException, JDOMException { 386 387 if (requestedProps != null) { 388 List propStatList = propertyRetriever.getPropertiesOfObject(requestedProps, 395 resourcePath, 396 getSlideContextPath(), 397 true); 398 Iterator iterator = propStatList.iterator(); 399 while (iterator.hasNext()) { 400 responseElement.addContent((Element)iterator.next()); 401 } 402 } 403 } 404 405 406 416 private void checkPreconditions(String updateSourcePath, String updateLabelName, String resourcePath) throws SlideException, PreconditionViolationException { 417 418 ViolatedPrecondition violatedPrecondition = getPreconditionViolation(updateSourcePath, 419 updateLabelName, 420 resourcePath); 421 if (violatedPrecondition != null) { 422 throw new PreconditionViolationException(violatedPrecondition, resourcePath); 423 } 424 } 425 426 427 436 private void handleException(JDOMException exception, Element statusElement, Element responseElement, NestedSlideException nestedSlideException) { 437 handleException(new SlideException("Nested exception: " + exception), 438 statusElement, 439 responseElement, 440 nestedSlideException); 441 } 442 443 452 private void handleException(SlideException exception, Element statusElement, Element responseElement, NestedSlideException nestedSlideException) { 453 454 nestedSlideException.addException(exception); 455 456 int errorCode = getErrorCode(exception); 457 statusElement.setText(HTTP_VERSION + " " + errorCode + " " + 458 WebdavStatus.getStatusText(errorCode)); 459 if (exception instanceof PreconditionViolationException) { 460 Element responseDescriptionElement = new Element(E_RESPONSEDESCRIPTION, 461 DNSP); 462 responseElement.addContent(responseDescriptionElement); 463 Element errorElement = MethodUtil.getPreconditionViolationError(((PreconditionViolationException)exception).getViolatedPrecondition()); 464 responseDescriptionElement.addContent(errorElement); 465 } 466 } 467 468 469 484 protected ViolatedPrecondition getPreconditionViolation(String updateSourcePath, String updateSourceLabel, String resourcePath) throws SlideException { 485 486 ViolatedPrecondition violatedPrecondition = null; 487 488 NodeRevisionDescriptors revisionDescriptors = 489 content.retrieve(slideToken, resourcePath); 490 NodeRevisionDescriptor revisionDescriptor = 491 content.retrieve(slideToken, revisionDescriptors); 492 ResourceKind resourceKind = AbstractResourceKind.determineResourceKind(token, 493 revisionDescriptors, 494 revisionDescriptor); 495 if ( ! (resourceKind instanceof CheckedInVersionControlled) ) { 496 return new ViolatedPrecondition(DeltavConstants.C_MUST_BE_CHECKED_IN_VERSION_CONTROLLED_RESOURCE, 497 WebdavStatus.SC_CONFLICT); 498 } 499 500 if (updateSourceLabel != null) { 501 try { 502 updateSourcePath = versioningHelper.getLabeledResourceUri(resourcePath, updateLabelName); 503 } 504 catch (LabeledRevisionNotFoundException e) { 505 return new ViolatedPrecondition(DeltavConstants.C_MUST_SELECT_VERSION_IN_HISTORY, 506 WebdavStatus.SC_CONFLICT); 507 } 508 } 509 510 String associatedVrUri = versioningHelper.getUriOfAssociatedVR(resourcePath); 511 String vcrHistoryUri = UriHandler.getUriHandler(associatedVrUri).getAssociatedHistoryUri(); 512 UriHandler vrUriHandler = UriHandler.getUriHandler(updateSourcePath); 513 boolean isVersionOfVcrHistory = false; 514 if (vrUriHandler.isVersionUri() && 515 vcrHistoryUri.equals(vrUriHandler.getAssociatedHistoryUri()) ) { 516 517 NodeRevisionDescriptors vrDescriptors = 518 content.retrieve(slideToken, updateSourcePath); 519 try { 520 content.retrieve(slideToken, vrDescriptors); 521 isVersionOfVcrHistory = true; 522 } 523 catch (RevisionDescriptorNotFoundException e) { 524 } 525 } 526 527 if ( ! isVersionOfVcrHistory ) { 528 return new ViolatedPrecondition(DeltavConstants.C_MUST_SELECT_VERSION_IN_HISTORY, 529 WebdavStatus.SC_CONFLICT); 530 } 531 532 return violatedPrecondition; 533 } 534 535 536 542 protected int getDepth() throws WebdavException { 543 return requestHeaders.getDepth(0); 544 } 545 546 547 } 548 549 550 | Popular Tags |