1 23 24 package org.apache.slide.webdav.method; 25 26 import java.util.*; 27 import org.apache.slide.content.*; 28 import org.apache.slide.macro.*; 29 import org.apache.slide.webdav.util.*; 30 31 import java.io.IOException ; 32 import org.apache.slide.common.NamespaceAccessToken; 33 import org.apache.slide.common.ServiceAccessException; 34 import org.apache.slide.common.SlideException; 35 import org.apache.slide.event.EventDispatcher; 36 import org.apache.slide.event.VetoException; 37 import org.apache.slide.lock.ObjectLockedException; 38 import org.apache.slide.security.AccessDeniedException; 39 import org.apache.slide.structure.LinkedObjectNotFoundException; 40 import org.apache.slide.structure.ObjectNode; 41 import org.apache.slide.structure.ObjectNotFoundException; 42 import org.apache.slide.structure.SubjectNode; 43 import org.apache.slide.util.Configuration; 44 import org.apache.slide.util.XMLValue; 45 import org.apache.slide.webdav.WebdavException; 46 import org.apache.slide.webdav.WebdavServletConfig; 47 import org.apache.slide.webdav.event.WebdavEvent; 48 import org.apache.slide.webdav.util.resourcekind.AbstractResourceKind; 49 import org.apache.slide.webdav.util.resourcekind.CheckedInVersionControlled; 50 import org.apache.slide.webdav.util.resourcekind.ResourceKind; 51 import org.apache.slide.webdav.util.resourcekind.VersionableImpl; 52 import org.jdom.Element; 53 import org.jdom.JDOMException; 54 import org.jdom.Namespace; 55 56 60 public class CopyMethod extends AbstractMultistatusResponseMethod implements DeltavConstants, AclConstants, BindConstants, CopyListener, DeleteListener, CopyRouteRedirector, WriteMethod { 61 62 63 64 67 protected VersioningHelper versioningHelper = null; 68 69 73 protected Map destinationDescriptorMap = new HashMap(); 74 75 79 protected Map destinationBackupDescriptorMap = new HashMap(); 80 81 84 protected String labelHeader = null; 85 86 private MacroParameters macroParameters = null; 87 88 89 91 92 98 public CopyMethod(NamespaceAccessToken token, WebdavServletConfig config) { 99 super(token, config); 100 } 101 102 103 105 110 protected void parseRequest() throws WebdavException { 111 super.parseRequest(); 112 113 versioningHelper = 114 VersioningHelper.getVersioningHelper(slideToken, token, req, resp, config); 115 labelHeader = WebdavUtils.fixTomcatHeader(requestHeaders.getLabel(), "UTF-8"); 116 } 117 118 123 protected void executeRequest() 124 throws WebdavException, IOException { 125 126 slideToken.setForceStoreEnlistment(true); 128 129 boolean isCollection = isCollection(sourceUri); 130 131 try { 133 if (isLockNull(sourceUri)) { 134 int statusCode = WebdavStatus.SC_NOT_FOUND; 135 sendError( statusCode, "lock-null resource", new Object []{sourceUri} ); 136 throw new WebdavException( statusCode ); 137 } 138 } 139 catch (ServiceAccessException e) { 140 int statusCode = getErrorCode((Exception )e); 141 sendError( statusCode, e ); 142 throw new WebdavException( statusCode ); 143 } 144 145 UriHandler destUh = UriHandler.getUriHandler(destinationUri); 147 148 if (destUh.isRestrictedUri()) { 149 boolean sendError = true; 150 if( destUh.isWorkspaceUri() || 151 destUh.isWorkingresourceUri() 152 ) { 153 try { 155 if ( WebdavEvent.COPY.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(WebdavEvent.COPY, new WebdavEvent(this)); 156 157 content.retrieve(slideToken, destinationUri); 158 sendError = false; 159 } 160 catch( SlideException x ) { 161 int statusCode = getErrorCode((SlideException)x); 162 sendError( statusCode, x ); 163 throw new WebdavException( statusCode ); 164 } 165 } 166 if( sendError ) { 167 int statusCode = WebdavStatus.SC_FORBIDDEN; 168 sendError( statusCode, getClass().getName()+".restrictedDestinationUri", new Object []{destinationUri} ); 169 throw new WebdavException( statusCode ); 170 } 171 } 172 173 try { 174 int depth = requestHeaders.getDepth(INFINITY); 176 if (depth != 0 && depth != INFINITY) { 177 int sc = WebdavStatus.SC_PRECONDITION_FAILED; 178 sendError( sc, "Invalid header Depth: "+depth ); 179 throw new WebdavException( sc ); 180 } 181 182 boolean recursive = (depth == INFINITY); 183 184 if (overwrite) { 185 macroParameters = new MacroParameters(recursive, true, true); 186 } else { 187 macroParameters = new MacroParameters(recursive, false, false); 188 } 189 190 boolean destinationExistsBefore = exists( destinationUri ); 191 192 if (!overwrite && destinationExistsBefore) { 193 int statusCode = WebdavStatus.SC_PRECONDITION_FAILED; 194 sendError( statusCode, getClass().getName()+".noOverwrite", new Object []{destinationUri} ); 195 throw new WebdavException( statusCode ); 196 } 197 198 macro.copy(slideToken, sourceUri, destinationUri, macroParameters, this, this, null, this); 199 200 if (overwrite && destinationExistsBefore) { 201 resp.setStatus(WebdavStatus.SC_NO_CONTENT); 202 } else { 203 resp.setStatus(WebdavStatus.SC_CREATED); 204 } 205 } catch (MacroException e) { 206 if(generateMultiStatusResponse(isCollection, e, requestUri)) { 207 String errorMessage = generateErrorMessage(e); 208 resp.setStatus(WebdavStatus.SC_MULTI_STATUS); 210 try { 211 resp.setContentType(TEXT_XML_UTF_8); 212 resp.getWriter().write(errorMessage); 213 } catch(IOException ex) { 214 int statusCode = WebdavStatus.SC_INTERNAL_SERVER_ERROR; 216 sendError( statusCode, e ); 217 throw new WebdavException( statusCode ); 218 } 219 } else { 220 SlideException exception = (SlideException)e.enumerateExceptions().nextElement(); 224 if (exception instanceof PreconditionViolationException) { 225 try { 226 sendPreconditionViolation((PreconditionViolationException)exception); 227 } catch(IOException ex) { 228 int statusCode = WebdavStatus.SC_INTERNAL_SERVER_ERROR; 230 sendError( statusCode, e ); 231 throw new WebdavException( statusCode ); 232 } 233 } 234 else { 235 int statusCode = getErrorCode( exception ); 236 sendError( statusCode, exception ); 237 throw new WebdavException( statusCode ); 238 } 239 } 240 throw new WebdavException(WebdavStatus.SC_ACCEPTED, false); 245 } 246 catch (WebdavException e) { 247 throw e; 248 } 249 catch (SlideException e) { 250 int statusCode = getErrorCode( e ); 251 sendError( statusCode, e ); 252 throw new WebdavException( statusCode ); 253 } 254 } 255 256 259 protected int getErrorCode(SlideException ex) { 260 try { 261 throw ex; 262 } catch(RevisionNotFoundException e) { 263 return WebdavStatus.SC_NOT_FOUND; 264 } catch (SlideException e) { 265 return super.getErrorCode(e); 266 } 267 } 268 269 275 private void restoreLiveProperties(String destinationUri, NodeRevisionDescriptor destinationNrd, NodeRevisionDescriptor existingNrd) { 276 277 Enumeration propertyEnum = destinationNrd.enumerateProperties(); 279 NodeProperty property = null; 280 while (propertyEnum.hasMoreElements()) { 281 property = (NodeProperty)propertyEnum.nextElement(); 282 if (isLivePropertyToRestore(destinationUri, property)) { 283 destinationNrd.removeProperty(property); 284 } 285 } 286 287 propertyEnum = existingNrd.enumerateProperties(); 289 property = null; 290 while (propertyEnum.hasMoreElements()) { 291 property = (NodeProperty)propertyEnum.nextElement(); 292 if (isLivePropertyToRestore(destinationUri, property)) { 293 destinationNrd.setProperty(property); 294 } 295 } 296 } 297 298 305 private boolean isLivePropertyToRestore(String uri, NodeProperty property) { 306 boolean isLivePropertyToRestore = property.isLiveProperty() && ( 307 DeltavConstants.DELTAV_PROPERTY_LIST.contains(property.getName()) || 308 AclConstants.ACL_PROPERTY_LIST.contains(property.getName()) || 309 BindConstants.BIND_PROPERTY_LIST.contains(property.getName()) || 310 P_CREATIONDATE.equals(property.getName()) || 311 ( P_DISPLAYNAME.equals(property.getName()) && 312 Configuration.useBinding(token.getUri(slideToken, uri).getStore()) ) 313 ); 314 return isLivePropertyToRestore; 315 } 316 317 324 private void resetDeltavProperties(NodeRevisionDescriptor revisionDescriptor, String resourcePath) { 325 326 PropertyHelper propertyHelper = PropertyHelper.getPropertyHelper(slideToken, token, getConfig()); 328 ResourceKind resourceKind = VersionableImpl.getInstance(); 329 Iterator initialPropertyIterator = 330 propertyHelper.createInitialProperties(resourceKind, resourcePath).iterator(); 331 NodeProperty property = null; 332 List initialDeltavProperties = new ArrayList(); 333 while (initialPropertyIterator.hasNext()) { 334 property = (NodeProperty)initialPropertyIterator.next(); 335 if (DeltavConstants.DELTAV_PROPERTY_LIST.contains(property.getName())) { 336 initialDeltavProperties.add(property); 337 } 338 } 339 340 Enumeration propertyEnum = revisionDescriptor.enumerateProperties(); 341 property = null; 342 int index = 0; 343 while (propertyEnum.hasMoreElements()) { 344 property = (NodeProperty)propertyEnum.nextElement(); 345 if (DeltavConstants.DELTAV_PROPERTY_LIST.contains(property.getName())) { 346 index = initialDeltavProperties.indexOf(property); 347 if (index >= 0) { 348 revisionDescriptor.setProperty((NodeProperty)initialDeltavProperties.get(index)); 349 } 350 else { 351 revisionDescriptor.removeProperty(property); 352 } 353 } 354 } 355 } 356 357 365 private void restoreBackupRevisionDescriptor(String destinationUri, NodeRevisionDescriptors destinationNrds) throws RevisionNotFoundException, ServiceAccessException, RevisionAlreadyExistException, ObjectNotFoundException, LinkedObjectNotFoundException, ObjectLockedException, AccessDeniedException, RevisionDescriptorNotFoundException, BranchNotFoundException, NodeNotVersionedException, VetoException { 366 367 NodeRevisionDescriptor backupNrd = 368 (NodeRevisionDescriptor)destinationBackupDescriptorMap.get(destinationUri); 369 if (backupNrd != null) { 370 try { 371 content.retrieve( slideToken, 372 destinationNrds, 373 NodeRevisionNumber.HIDDEN_0_0 ); 374 content.store( slideToken, 375 destinationNrds.getUri(), 376 backupNrd, 377 null ); 378 } 379 catch (RevisionDescriptorNotFoundException e) { 380 content.create( slideToken, 381 destinationNrds.getUri(), 382 null, 383 backupNrd, 384 null ); } 386 } 387 } 388 389 390 392 403 public CopyRoute getRedirectedCopyRoute(CopyRoute copyRoute) throws SlideException { 404 405 if (Configuration.useVersionControl()) { 406 407 String sourceUri = copyRoute.getSourceUri(); 408 String destinationUri = copyRoute.getDestinationUri(); 409 410 try { 411 sourceUri = versioningHelper.getLabeledResourceUri(sourceUri, labelHeader); 412 copyRoute = new CopyRoute(sourceUri, destinationUri); 413 } 414 catch (LabeledRevisionNotFoundException e) { 415 ViolatedPrecondition violatedPrecondition = 416 new ViolatedPrecondition(DeltavConstants.C_MUST_SELECT_VERSION_IN_HISTORY, 417 WebdavStatus.SC_CONFLICT); 418 throw new PreconditionViolationException(violatedPrecondition, sourceUri); 419 } 420 } 421 422 return copyRoute; 423 } 424 425 426 428 440 public void beforeCopy(String sourceUri, String destinationUri, boolean isRootOfCopy) throws SlideException { 441 if(Configuration.useVersionControl()) { 442 443 UriHandler sourceUh = UriHandler.getUriHandler(sourceUri); 444 if (sourceUh.isHistoryUri()) { 445 throw new PreconditionViolationException( 446 new ViolatedPrecondition(DeltavConstants.C_CANNOT_COPY_HISTORY, WebdavStatus.SC_FORBIDDEN), sourceUri); 447 } 448 449 if (!macroParameters.isDeleteCreate()) { 450 beforeUpdateOrDelete( destinationUri ); 451 } 452 } 453 if (isRootOfCopy && Configuration.useBinding(token.getUri(slideToken, destinationUri).getStore())) { 454 Map parentBindings = new HashMap(); 456 try { 457 NodeRevisionDescriptor destinationNrd = 458 content.retrieve( slideToken, content.retrieve(slideToken, destinationUri) ); 459 XMLValue v = new XMLValue( (String )destinationNrd.getProperty( P_PARENT_SET ).getValue() ); 460 Iterator i = v.iterator(); 461 while (i.hasNext()) { 462 Namespace dnsp = Namespace.getNamespace(S_DAV); 463 Element parentElm = (Element)i.next(); 464 String segment = parentElm.getChild(E_SEGMENT, dnsp).getTextTrim(); 465 String href = parentElm.getChild(E_HREF, dnsp).getTextTrim(); 466 parentBindings.put( href, segment ); 467 } 468 } 469 catch( ServiceAccessException x ) { 470 throw x; 471 } 472 catch (SlideException e) {} 473 catch (JDOMException e) {} 474 macroParameters.setParameter( Macro.PARENT_BINDINGS, parentBindings ); 475 } 476 } 477 478 489 public void afterCopy(String sourceUri, String destinationUri, boolean isRootOfCopy, boolean destinationExists) throws SlideException { 490 491 if(Configuration.useVersionControl()) { 492 493 NodeRevisionDescriptors destinationNrds = content.retrieve( slideToken, destinationUri); 494 NodeRevisionDescriptor destinationNrd = content.retrieve( slideToken, destinationNrds); 495 496 restoreBackupRevisionDescriptor(destinationUri, destinationNrds); 498 499 NodeRevisionDescriptor existingNrd = 500 (NodeRevisionDescriptor)destinationDescriptorMap.get(destinationUri); 501 if (existingNrd != null) { 502 503 restoreLiveProperties(destinationUri, destinationNrd, existingNrd); 505 } 506 else { 507 508 resetDeltavProperties(destinationNrd, destinationUri); 510 } 511 512 versioningHelper.setWorkspaceProperty(destinationUri, destinationNrd); 514 515 destinationNrd.setLastModified( new Date() ); destinationNrd.setETag( PropertyHelper.computeEtag(destinationUri, destinationNrd) ); if (!destinationExists) { 519 String creator = ((SubjectNode)security.getPrincipal(slideToken)).getPath().lastSegment(); 521 destinationNrd.setOwner(creator); 522 } 523 524 content.store(slideToken, destinationNrds.getUri(), destinationNrd, null); 525 526 boolean mustCheckin = versioningHelper.mustCheckinAutoVersionedVCR(slideToken, destinationNrds, destinationNrd); 528 if (mustCheckin) { 529 try { 530 versioningHelper.checkin(destinationUri, false, false, true ); } 532 catch (IOException e) { 533 throw new SlideException("Checkin failed: " + e.getMessage()); 534 } 535 catch (JDOMException e) { 536 throw new SlideException("Checkin failed: " + e.getMessage()); 537 } 538 } 539 540 if( isAutoVersionControl(destinationUri) && !isCollection(destinationUri) && !isExcludedForVersionControl(destinationUri) ) { 542 versioningHelper.versionControl(destinationUri); 543 } 544 545 } 546 if (isRootOfCopy && Configuration.useBinding(token.getUri(slideToken, destinationUri).getStore())) { 547 if (macroParameters.getParameter(Macro.PARENT_BINDINGS) != null) { 549 Map parentBindings = (Map)macroParameters.getParameter(Macro.PARENT_BINDINGS); 550 Iterator i = parentBindings.entrySet().iterator(); 551 while (i.hasNext()) { 552 Map.Entry me = (Map.Entry)i.next(); 553 ObjectNode parentNode = structure.retrieve( slideToken, (String )me.getKey() ); 554 ObjectNode destinationNode = structure.retrieve( slideToken, destinationUri ); 555 String segment = (String )me.getValue(); 556 structure.addBinding( slideToken, parentNode, segment, destinationNode ); 557 } 558 } 559 } 560 } 561 562 563 564 566 577 public void beforeDelete(String destinationUri) throws SlideException { 578 beforeUpdateOrDelete( destinationUri ); 579 } 580 581 592 private void beforeUpdateOrDelete(String destinationUri) throws SlideException { 593 if( Configuration.useVersionControl() ) { 594 NodeRevisionDescriptors destinationNrds = null; 595 NodeRevisionDescriptor destinationNrd = null; 596 597 try { 598 destinationNrds = content.retrieve( slideToken, destinationUri); 599 destinationNrd = content.retrieve( slideToken, destinationNrds); 600 } 601 catch (ObjectNotFoundException e) {} 602 603 if (destinationNrds != null && destinationNrd != null) { 604 605 ResourceKind resourceKind = AbstractResourceKind.determineResourceKind(token, destinationUri, destinationNrd); 606 if (resourceKind instanceof CheckedInVersionControlled) { 607 608 String autoVersion = versioningHelper.getAutoVersionElementName(destinationNrd); 610 if (autoVersion == null) { 611 autoVersion = ""; 612 } 613 if ( !E_CHECKOUT_CHECKIN.equals(autoVersion) && 614 !E_CHECKOUT_UNLOCKED_CHECKIN.equals(autoVersion) && 615 !E_CHECKOUT.equals(autoVersion) && 616 !E_CHECKOUT_IGNORE_UNLOCK.equals(autoVersion) && 617 !E_LOCKED_CHECKOUT.equals(autoVersion) ) { 618 throw new PreconditionViolationException(new ViolatedPrecondition(C_CANNOT_MODIFY_VERSION_CONTROLLED_CONTENT, 619 WebdavStatus.SC_FORBIDDEN), destinationUri); 620 } 621 if ( E_LOCKED_CHECKOUT.equals(autoVersion) && 622 ( !versioningHelper.isWriteLocked(slideToken, destinationNrds) ) ) { 623 throw new PreconditionViolationException(new ViolatedPrecondition(C_CANNOT_MODIFY_VERSION_CONTROLLED_CONTENT, 624 WebdavStatus.SC_FORBIDDEN), destinationUri); 625 } 626 } 627 628 UriHandler uriHandler = UriHandler.getUriHandler(destinationUri); 630 if (uriHandler.isVersionUri()) { 631 throw new PreconditionViolationException(new ViolatedPrecondition(C_CANNOT_MODIFY_VERSION, 632 WebdavStatus.SC_FORBIDDEN), destinationUri); 633 } 634 635 if( Configuration.useVersionControl() && 637 (resourceKind instanceof CheckedInVersionControlled) && 638 versioningHelper.mustCheckoutAutoVersionedVCR(destinationNrds, destinationNrd) ) { 639 640 try { 641 versioningHelper.checkout(destinationNrds, destinationNrd, false, false, true ); 642 } 643 catch (IOException e) { 644 throw new SlideException("Checkout failed: " + e.getMessage()); 645 } 646 catch (JDOMException e) { 647 throw new SlideException("Checkout failed: " + e.getMessage()); 648 } 649 } 650 651 try { 655 NodeRevisionDescriptor backupNrd = 656 content.retrieve( slideToken, destinationNrds, NodeRevisionNumber.HIDDEN_0_0 ); 657 destinationBackupDescriptorMap.put(destinationUri, backupNrd); 658 } 659 catch (RevisionDescriptorNotFoundException e) { 660 } 661 destinationDescriptorMap.put(destinationUri, destinationNrd); 662 } 663 } 664 } 665 666 676 public void afterDelete(String targetUri) throws SlideException { 677 } 678 679 680 681 682 } 683 684 685 686 687 688 689 | Popular Tags |