1 23 24 package org.apache.slide.webdav.method; 25 26 import java.io.IOException ; 27 import java.util.Iterator ; 28 29 import org.apache.slide.common.NamespaceAccessToken; 30 import org.apache.slide.common.ServiceAccessException; 31 import org.apache.slide.common.SlideException; 32 import org.apache.slide.content.NodeProperty; 33 import org.apache.slide.content.NodeRevisionDescriptor; 34 import org.apache.slide.content.NodeRevisionDescriptors; 35 import org.apache.slide.content.NodeRevisionNumber; 36 import org.apache.slide.content.RevisionDescriptorNotFoundException; 37 import org.apache.slide.content.RevisionNotFoundException; 38 import org.apache.slide.content.NodeProperty.NamespaceCache; 39 import org.apache.slide.event.EventDispatcher; 40 import org.apache.slide.macro.CopyListener; 41 import org.apache.slide.macro.DeleteListener; 42 import org.apache.slide.macro.Macro; 43 import org.apache.slide.macro.MacroException; 44 import org.apache.slide.macro.MacroParameters; 45 import org.apache.slide.search.RequestedResource; 46 import org.apache.slide.search.Search; 47 import org.apache.slide.search.SearchQuery; 48 import org.apache.slide.search.SearchQueryResult; 49 import org.apache.slide.structure.ObjectNode; 50 import org.apache.slide.structure.ObjectNotFoundException; 51 import org.apache.slide.util.Configuration; 52 import org.apache.slide.webdav.WebdavException; 53 import org.apache.slide.webdav.WebdavServletConfig; 54 import org.apache.slide.webdav.event.WebdavEvent; 55 import org.apache.slide.webdav.util.DaslConstants; 56 import org.apache.slide.webdav.util.DeltavConstants; 57 import org.apache.slide.webdav.util.PreconditionViolationException; 58 import org.apache.slide.webdav.util.PropertyHelper; 59 import org.apache.slide.webdav.util.UriHandler; 60 import org.apache.slide.webdav.util.VersioningHelper; 61 import org.apache.slide.webdav.util.ViolatedPrecondition; 62 import org.apache.slide.webdav.util.WebdavStatus; 63 import org.apache.slide.webdav.util.resourcekind.AbstractResourceKind; 64 import org.apache.slide.webdav.util.resourcekind.CheckedOutVersionControlled; 65 import org.apache.slide.webdav.util.resourcekind.DeltavCompliantUnmappedUrl; 66 import org.apache.slide.webdav.util.resourcekind.ResourceKind; 67 import org.apache.slide.webdav.util.resourcekind.VersionControlled; 68 import org.apache.slide.webdav.util.resourcekind.Working; 69 import org.jdom.Element; 70 import org.jdom.JDOMException; 71 72 76 public class MoveMethod extends AbstractMultistatusResponseMethod implements DeltavConstants, DeleteListener, CopyListener, WriteMethod { 77 78 79 82 protected VersioningHelper versioningHelper = null; 83 84 87 protected PropertyHelper propertyHelper = null; 88 89 92 protected boolean isRequestSourceWorkspace = false; 93 94 98 protected boolean isCopySourceVCR = false; 99 100 104 protected Element basicSearch = null; 105 106 110 protected Element literal = null; 111 112 private boolean destinationExistsBefore = false; 113 114 116 117 123 public MoveMethod(NamespaceAccessToken token, WebdavServletConfig config) { 124 super(token, config); 125 } 126 127 128 130 131 132 137 protected void executeRequest() 138 throws WebdavException, IOException { 139 140 versioningHelper = VersioningHelper.getVersioningHelper(slideToken, 141 token, 142 req, 143 resp, 144 config); 145 propertyHelper = PropertyHelper.getPropertyHelper(slideToken, token, getConfig()); 146 147 slideToken.setForceStoreEnlistment(true); 149 150 try { 152 if (isLockNull(sourceUri)) { 153 int statusCode = WebdavStatus.SC_NOT_FOUND; 154 sendError( statusCode, "lock-null resource", new Object []{sourceUri} ); 155 throw new WebdavException( statusCode ); 156 } else if (isLocked(sourceUri)) { 157 int statusCode = WebdavStatus.SC_LOCKED; 158 sendError( statusCode, getClass().getName()+".noLocked", new Object []{sourceUri} ); 159 throw new WebdavException( statusCode ); 160 } 161 } 162 catch (ServiceAccessException e) { 163 int statusCode = getErrorCode((Exception )e); 164 sendError( statusCode, e ); 165 throw new WebdavException( statusCode ); 166 } 167 168 int depth = requestHeaders.getDepth(INFINITY); 169 if (depth < INFINITY) { 170 int sc = WebdavStatus.SC_PRECONDITION_FAILED; 171 sendError( sc, "Invalid header Depth: "+depth ); 172 throw new WebdavException( sc ); 173 } 174 175 MacroParameters macroParameters = null; 176 boolean isCollection = isCollection(sourceUri); 177 178 if (overwrite) { 179 macroParameters = Macro.RECURSIVE_OVERWRITE_PARAMETERS; 180 } else { 181 macroParameters = Macro.DEFAULT_PARAMETERS; 182 } 183 184 UriHandler destinationUriHandler = UriHandler.getUriHandler(destinationUri); 186 if (destinationUriHandler.isRestrictedUri()) { 187 int statusCode = WebdavStatus.SC_FORBIDDEN; 188 sendError( statusCode, getClass().getName()+".restrictedDestinationUri", new Object []{destinationUri} ); 189 throw new WebdavException( statusCode ); 190 } 191 192 UriHandler sourceUriHandler = UriHandler.getUriHandler(sourceUri); 193 isRequestSourceWorkspace = sourceUriHandler.isWorkspaceUri(); 194 195 try { 196 ViolatedPrecondition violatedPrecondition = getPreconditionViolation(sourceUri, destinationUri); 198 if (violatedPrecondition != null) { 199 PreconditionViolationException e = 200 new PreconditionViolationException(violatedPrecondition, sourceUri); 201 sendPreconditionViolation(e); 202 throw e; 203 } 204 205 destinationExistsBefore = exists(destinationUri); 206 if (!overwrite && destinationExistsBefore) { 207 int statusCode = WebdavStatus.SC_PRECONDITION_FAILED; 208 sendError( statusCode, getClass().getName()+".noOverwrite", new Object []{destinationUri} ); 209 throw new WebdavException( statusCode ); 210 } 211 if ( WebdavEvent.MOVE.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(WebdavEvent.MOVE, new WebdavEvent(this)); 212 213 macro.move(slideToken, sourceUri, destinationUri, macroParameters, null, this, null, this); 214 215 if (overwrite && destinationExistsBefore) { 216 resp.setStatus(WebdavStatus.SC_NO_CONTENT); 217 } else { 218 resp.setStatus(WebdavStatus.SC_CREATED); 219 } 220 } catch (MacroException e) { 221 if(generateMultiStatusResponse(isCollection, e, requestUri)) { 222 String errorMessage = generateErrorMessage(e); 223 resp.setStatus(WebdavStatus.SC_MULTI_STATUS); 225 try { 226 resp.setContentType(TEXT_XML_UTF_8); 227 resp.getWriter().write(errorMessage); 228 } catch(IOException ex) { 229 int statusCode = WebdavStatus.SC_INTERNAL_SERVER_ERROR; 231 sendError( statusCode, e ); 232 throw new WebdavException( statusCode ); 233 } 234 } else { 235 SlideException exception = (SlideException)e.enumerateExceptions().nextElement(); 239 if (exception instanceof PreconditionViolationException) { 240 try { 241 sendPreconditionViolation((PreconditionViolationException)exception); 242 } catch(IOException ex) { 243 int statusCode = WebdavStatus.SC_INTERNAL_SERVER_ERROR; 245 sendError( statusCode, e ); 246 throw new WebdavException( statusCode ); 247 } 248 } 249 else { 250 int statusCode = getErrorCode( exception ); 251 sendError( statusCode, exception ); 252 throw new WebdavException( statusCode ); 253 } 254 } 255 throw new WebdavException(WebdavStatus.SC_ACCEPTED, false); 260 } 261 catch (SlideException e) { 262 int statusCode = getErrorCode( e ); 263 sendError( statusCode, e ); 264 throw new WebdavException( statusCode ); 265 } 266 } 267 268 269 272 protected int getErrorCode(SlideException ex) { 273 try { 274 throw ex; 275 } catch(RevisionNotFoundException e) { 276 return WebdavStatus.SC_NOT_FOUND; 277 } catch (SlideException e) { 278 return super.getErrorCode(e); 279 } 280 } 281 282 296 private ViolatedPrecondition getPreconditionViolation(String sourceUri, String destinationUri) throws SlideException { 297 298 ViolatedPrecondition violatedPrecondition = null; 299 if( Configuration.useVersionControl() ) { 300 301 if (isRequestSourceWorkspace) { 302 303 UriHandler destinationUriHandler = UriHandler.getUriHandler(destinationUri); 304 NodeRevisionDescriptors destinationRevisionDescriptors = null; 305 NodeRevisionDescriptor destinationRevisionDescriptor = null; 306 try { 307 destinationRevisionDescriptors = content.retrieve( slideToken, destinationUri); 308 destinationRevisionDescriptor = content.retrieve( slideToken, destinationRevisionDescriptors); 309 } 310 catch( ObjectNotFoundException e ) {}; 312 ResourceKind destinationResourceKind = 313 AbstractResourceKind.determineResourceKind( token, destinationUri, destinationRevisionDescriptor ); 314 315 if( !(destinationResourceKind instanceof DeltavCompliantUnmappedUrl) ) { 316 return new ViolatedPrecondition(C_RESOURCE_MUST_BE_NULL, 317 WebdavStatus.SC_CONFLICT); 318 } 319 if( !destinationUriHandler.isWorkspaceUri() ) { 320 return new ViolatedPrecondition(C_WORKSPACE_LOCATION_OK, 321 WebdavStatus.SC_CONFLICT); 322 } 323 } 324 } 325 if (isCollection(sourceUri)) { 326 UriHandler destinationUriHandler = UriHandler.getUriHandler(destinationUri); 327 ObjectNode destinationParentNode = 328 structure.retrieve(slideToken, destinationUriHandler.getParentUriHandler().toString()); 329 ObjectNode sourceNode = 330 structure.retrieve(slideToken, sourceUri); 331 if (isDescendant(destinationParentNode, sourceNode)) { 332 return new ViolatedPrecondition(C_CYCLE_ALLOWED, WebdavStatus.SC_FORBIDDEN); 333 } 334 } 335 336 return violatedPrecondition; 337 } 338 339 341 353 public void beforeCopy(String sourceUri, String destinationUri, boolean isRootOfCopy) throws SlideException { 354 355 if( Configuration.useVersionControl() ) { 356 357 UriHandler uriHandler = UriHandler.getUriHandler(sourceUri); 358 if (uriHandler.isVersionUri()) { 359 throw new PreconditionViolationException(new ViolatedPrecondition(DeltavConstants.C_CANNOT_RENAME_VERSION, 360 WebdavStatus.SC_FORBIDDEN), 361 sourceUri); 362 } 363 if (uriHandler.isHistoryUri()) { 364 throw new PreconditionViolationException(new ViolatedPrecondition(DeltavConstants.C_CANNOT_RENAME_HISTORY, 365 WebdavStatus.SC_FORBIDDEN), 366 sourceUri); 367 } 368 if (uriHandler.isWorkingresourceUri()) { 369 throw new PreconditionViolationException(new ViolatedPrecondition(DeltavConstants.C_CANNOT_RENAME_WORKING_RESOURCE, 370 WebdavStatus.SC_FORBIDDEN), 371 sourceUri); 372 } 373 374 NodeRevisionDescriptors sourceRevisionDescriptors = 375 content.retrieve( slideToken, sourceUri); 376 NodeRevisionDescriptor sourceRevisionDescriptor = 377 content.retrieve( slideToken, sourceRevisionDescriptors); 378 ResourceKind resourceKind = AbstractResourceKind.determineResourceKind(token, 379 sourceRevisionDescriptors, 380 sourceRevisionDescriptor); 381 isCopySourceVCR = (resourceKind instanceof VersionControlled); 382 383 if(resourceKind instanceof CheckedOutVersionControlled || resourceKind instanceof Working) { 386 String vrUri = 387 VersioningHelper.getUriOfAssociatedVR(token, slideToken, content, sourceUri); 388 NodeRevisionDescriptors vrNrds = content.retrieve(slideToken, vrUri); 389 NodeRevisionDescriptor vrNrd = content.retrieve(slideToken, vrNrds); 390 try { 391 PropertyHelper.removeHrefFromProperty(vrNrd, P_CHECKOUT_SET, sourceUri); 392 PropertyHelper.addHrefToProperty(vrNrd, P_CHECKOUT_SET, destinationUri); 393 content.store(slideToken, vrNrds.getUri(), vrNrd, null); 394 } 395 catch (JDOMException e) { 396 throw new SlideException( 397 "Unable to update DAV:checkout-set of "+vrUri+": "+e.getMessage() ); 398 } 399 } 400 } 401 } 402 403 414 public void afterCopy(String sourceUri, String destinationUri, boolean isRootOfCopy, boolean destinationExists) throws SlideException { 415 416 if( Configuration.useVersionControl() ) { 417 418 NodeRevisionDescriptors sourceNrds = 419 content.retrieve( slideToken, sourceUri); 420 NodeRevisionDescriptors destinationNrds = 421 content.retrieve( slideToken, destinationUri); 422 NodeRevisionDescriptor destinationNrd = 423 content.retrieve( slideToken, destinationNrds ); 424 425 try { 427 NodeRevisionDescriptor sourceNrd00 = 428 content.retrieve( slideToken, sourceNrds, NodeRevisionNumber.HIDDEN_0_0 ); 429 NodeRevisionDescriptor destinationNrd00 = sourceNrd00.cloneObject(); 430 431 try { 432 content.retrieve( slideToken, destinationNrds, NodeRevisionNumber.HIDDEN_0_0 ); 433 content.store( slideToken, destinationUri, destinationNrd00, null ); } 435 catch( RevisionDescriptorNotFoundException x ) { 436 content.create( slideToken, destinationUri, null, destinationNrd00, null ); } 438 } 439 catch (ServiceAccessException e) { 440 throw e; 441 } 442 catch (SlideException e) {} 443 444 handleWorkspacePostconditions(destinationNrd, destinationUri); 445 handleWorkingResourcePostconditions(sourceUri, destinationUri); 446 } 447 } 448 449 460 private void handleWorkingResourcePostconditions(String sourceUri, String destinationUri) throws SlideException { 461 462 if (isCopySourceVCR) { 463 464 Element basicSearch = getWorkingResourceSearchElement(sourceUri); 465 String grammarNamespace = basicSearch.getNamespaceURI(); 466 Search searchHelper = token.getSearchHelper(); 467 468 SearchQuery searchQuery = searchHelper.createSearchQuery( 469 grammarNamespace, 470 basicSearch, 471 slideToken, 472 Integer.MAX_VALUE, 473 getSlideContextPath() + sourceUri); 474 475 SearchQueryResult queryResult = searchHelper.search(slideToken, searchQuery); 476 477 Iterator queryResultIterator = queryResult.iterator(); 478 RequestedResource requestedResource = null; 479 NodeRevisionDescriptors workingResourceRevisionDescriptors = null; 480 NodeRevisionDescriptor workingResourceRevisionDescriptor = null; 481 NodeProperty autoUpdateProperty = null; 482 String workingResourceUri = null; 483 484 while (queryResultIterator.hasNext()) { 485 486 requestedResource = (RequestedResource)queryResultIterator.next(); 487 workingResourceUri = requestedResource.getUri(); 488 workingResourceRevisionDescriptors = 489 content.retrieve( slideToken, workingResourceUri); 490 workingResourceRevisionDescriptor = 491 content.retrieve( slideToken, workingResourceRevisionDescriptors); 492 autoUpdateProperty = new NodeProperty(P_AUTO_UPDATE, 493 propertyHelper.createHrefValue(destinationUri)); 494 workingResourceRevisionDescriptor.setProperty(autoUpdateProperty); 495 content.store(slideToken, 496 workingResourceRevisionDescriptors.getUri(), 497 workingResourceRevisionDescriptor, 498 null); 499 } 500 } 501 } 502 503 512 protected Element getWorkingResourceSearchElement(String resourcePath) { 513 514 if (basicSearch == null) { 515 basicSearch = new Element(DaslConstants.E_BASICSEARCH, 516 DNSP); 517 518 Element select = new Element(DaslConstants.E_SELECT, 519 DNSP); 520 basicSearch.addContent(select); 521 Element prop = new Element(E_PROP, 522 DNSP); 523 select.addContent(prop); 524 Element autoUpdate = new Element(P_AUTO_UPDATE, 525 DNSP); 526 prop.addContent(autoUpdate); 527 528 Element from = new Element(DaslConstants.E_FROM, 529 DNSP); 530 basicSearch.addContent(from); 531 Element scope = new Element(DaslConstants.E_SCOPE, 532 DNSP); 533 from.addContent(scope); 534 Element href = new Element(E_HREF, 535 DNSP); 536 scope.addContent(href); 537 href.setText(""); 538 539 Iterator excludeIterator = propertyHelper.getNonVcrPathExcludeList().iterator(); 540 while (excludeIterator.hasNext()) { 541 scope.addContent((Element)excludeIterator.next()); 542 } 543 544 Element where = new Element(DaslConstants.E_WHERE, 545 DNSP); 546 basicSearch.addContent(where); 547 Element propcontains = new Element(DaslConstants.E_PROPCONTAINS, 548 NamespaceCache.SLIDE_NAMESPACE); 549 where.addContent(propcontains); 550 propcontains.addContent((Element)prop.clone()); 551 literal = new Element(DaslConstants.E_LITERAL, 552 DNSP); 553 propcontains.addContent(literal); 554 } 555 literal.setText(resourcePath); 556 557 return basicSearch; 558 } 559 560 572 protected void handleWorkspacePostconditions(NodeRevisionDescriptor revisionDescriptor, String resourceUri) throws SlideException { 573 574 if( Configuration.useVersionControl() ) { 575 576 if (isRequestSourceWorkspace) { 577 revisionDescriptor.setProperty( 579 new NodeProperty( P_WORKSPACE, propertyHelper.createHrefValue(this.destinationUri)) ); 580 } 581 else { 582 versioningHelper.setWorkspaceProperty(resourceUri, revisionDescriptor); 584 } 585 content.store(slideToken, resourceUri, revisionDescriptor, null); 586 } 587 } 588 589 590 592 603 public void beforeDelete(String targetUri) throws SlideException { 604 } 605 606 616 public void afterDelete(String targetUri) throws SlideException { 617 } 618 } 619 620 621 | Popular Tags |