CopyMethod.java
| Index Score | ||
|---|---|---|
![]() |
![]() |
org.apache.slide.webdav.method |
![]() |
![]() |
Jakarta Slide |
View: Reasons, Metrics, Source Code
These are the metrics that contribute to the Enerjy Score for this file, ranked by impact. So the metrics listed at the top influence the score to a greater extent that the metrics listed at the bottom.
/*
* $Header$
* $Revision: 208545 $
* $Date: 2005-02-25 12:07:59 -0500 (Fri, 25 Feb 2005) $
*
* ====================================================================
*
* Copyright 1999-2002 The Apache Software Foundation
*
* Licensed 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.slide.webdav.method;
import java.util.*;
import org.apache.slide.content.*;
import org.apache.slide.macro.*;
import org.apache.slide.webdav.util.*;
import java.io.IOException;
import org.apache.slide.common.NamespaceAccessToken;
import org.apache.slide.common.ServiceAccessException;
import org.apache.slide.common.SlideException;
import org.apache.slide.event.EventDispatcher;
import org.apache.slide.event.VetoException;
import org.apache.slide.lock.ObjectLockedException;
import org.apache.slide.security.AccessDeniedException;
import org.apache.slide.structure.LinkedObjectNotFoundException;
import org.apache.slide.structure.ObjectNode;
import org.apache.slide.structure.ObjectNotFoundException;
import org.apache.slide.structure.SubjectNode;
import org.apache.slide.util.Configuration;
import org.apache.slide.util.XMLValue;
import org.apache.slide.webdav.WebdavException;
import org.apache.slide.webdav.WebdavServletConfig;
import org.apache.slide.webdav.event.DetailedWebdavEvent;
import org.apache.slide.webdav.event.WebdavEvent;
import org.apache.slide.webdav.util.resourcekind.AbstractResourceKind;
import org.apache.slide.webdav.util.resourcekind.CheckedInVersionControlled;
import org.apache.slide.webdav.util.resourcekind.ResourceKind;
import org.apache.slide.webdav.util.resourcekind.VersionableImpl;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
/**
* COPY Method.
*
*/
public class CopyMethod extends AbstractMultistatusResponseMethod implements DeltavConstants,
AclConstants, BindConstants, CopyListener, DeleteListener, CopyRouteRedirector,
WriteMethod, FineGrainedLockingMethod {
/**
* Maps the URI of a destination to its descriptor.
* Used by {@link #beforeCopy beforeCopy()} and {@link #afterCopy afterCopy()}.
*/
protected Map destinationDescriptorMap = new HashMap();
/**
* Maps the URI of a destination to its backup descriptor.
* Used by {@link #beforeCopy beforeCopy()} and {@link #afterCopy afterCopy()}.
*/
protected Map destinationBackupDescriptorMap = new HashMap();
/**
* The value of the <code>Label</code> header.
*/
protected String labelHeader = null;
private MacroParameters macroParameters = null;
// ----------------------------------------------------------- Constructors
/**
* Constructor.
*
* @param token the token for accessing the namespace
* @param config configuration of the WebDAV servlet
*/
public CopyMethod(NamespaceAccessToken token, WebdavServletConfig config) {
super(token, config);
}
/**
* @see org.apache.slide.webdav.method.FineGrainedLockingMethod#acquireFineGrainLocks()
*/
public void acquireFineGrainLocks() {
acquireStandardLocks(destinationUri);
acquireStandardLocks(sourceUri);
// changes this and parent
acquireLock(destinationUri, WRITE_LOCK); // effectively means recursive write locks
acquireParentLock(destinationUri, WRITE_LOCK);
// XXX fake resursivly lock to source uri using write lock
acquireLock(sourceUri, WRITE_LOCK);
}
// ------------------------------------------------------ Protected Methods
/**
* Parse request.
*
* @exception WebdavException Does not happen
*/
protected void parseRequest() throws WebdavException {
super.parseRequest();
labelHeader = WebdavUtils.fixTomcatHeader(requestHeaders.getLabel(), "UTF-8");
}
/**
* Execute request.
*
* @exception WebdavException Unrecoverable error occured while copying
*/
protected void executeRequest()
throws WebdavException, IOException {
// Prevent dirty reads
slideToken.setForceStoreEnlistment(true);
boolean isCollection = isCollection(sourceUri);
// check lock-null resources
try {
if (isLockNull(sourceUri)) {
int statusCode = WebdavStatus.SC_NOT_FOUND;
sendError( statusCode, "lock-null resource", new Object[]{sourceUri} );
throw new WebdavException( statusCode );
}
}
catch (ServiceAccessException e) {
int statusCode = getErrorCode((Exception)e);
sendError( statusCode, e );
throw new WebdavException( statusCode );
}
// check destination URI
UriHandler destUh = UriHandler.getUriHandler(destinationUri);
if (destUh.isRestrictedUri()) {
boolean sendError = true;
if( destUh.isWorkspaceUri() || destUh.isWorkingresourceUri() ) {
// COPY on existing WSs or WRs is *not* restricted !!!
try {
content.retrieve(slideToken, destinationUri);
sendError = false;
}
catch( SlideException x ) {
int statusCode = getErrorCode(x);
sendError( statusCode, x );
throw new WebdavException( statusCode );
}
}
if( sendError ) {
int statusCode = WebdavStatus.SC_FORBIDDEN;
sendError( statusCode, getClass().getName()+".restrictedDestinationUri", new Object[]{destinationUri} );
throw new WebdavException( statusCode );
}
}
try {
// compare resource types of source and destination
int depth = requestHeaders.getDepth(INFINITY);
if (depth != 0 && depth != INFINITY) {
int sc = WebdavStatus.SC_PRECONDITION_FAILED;
sendError( sc, "Invalid header Depth: "+depth );
throw new WebdavException( sc );
}
boolean recursive = (depth == INFINITY);
if (overwrite) {
macroParameters = new MacroParameters(recursive, true, true);
} else {
macroParameters = new MacroParameters(recursive, false, false);
}
boolean destinationExistsBefore = exists( destinationUri );
if (!overwrite && destinationExistsBefore) {
int statusCode = WebdavStatus.SC_PRECONDITION_FAILED;
sendError( statusCode, getClass().getName()+".noOverwrite", new Object[]{destinationUri} );
throw new WebdavException( statusCode );
}
if ( WebdavEvent.COPY.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(WebdavEvent.COPY, new WebdavEvent(this));
macro.copy(slideToken, sourceUri, destinationUri, macroParameters, this, this, null, this);
if (overwrite && destinationExistsBefore) {
resp.setStatus(WebdavStatus.SC_NO_CONTENT);
} else {
resp.setStatus(WebdavStatus.SC_CREATED);
}
} catch (MacroException e) {
if(generateMultiStatusResponse(isCollection, e, requestUri)) {
String errorMessage = generateErrorMessage(e);
// Write it on the servlet writer
resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
try {
resp.setContentType(TEXT_XML_UTF_8);
resp.getWriter().write(errorMessage);
} catch(IOException ex) {
// Critical error ... Servlet container is dead or something
int statusCode = WebdavStatus.SC_INTERNAL_SERVER_ERROR;
sendError( statusCode, e );
throw new WebdavException( statusCode );
}
} else {
// Returning 207 on non-collection requests is generally
// considered bad. So let's not do it, since this way
// makes clients generally behave better.
SlideException exception = (SlideException)e.enumerateExceptions().nextElement();
if (exception instanceof PreconditionViolationException) {
try {
sendPreconditionViolation((PreconditionViolationException)exception);
} catch(IOException ex) {
// Critical error ... Servlet container is dead or something
int statusCode = WebdavStatus.SC_INTERNAL_SERVER_ERROR;
sendError( statusCode, e );
throw new WebdavException( statusCode );
}
}
else {
int statusCode = getErrorCode( exception );
sendError( statusCode, exception );
throw new WebdavException( statusCode );
}
}
//
// make sure the transaction is aborted
// throw any WebDAV exception to indicate the transaction wants to be aborted
//
throw new WebdavException(WebdavStatus.SC_ACCEPTED, false);
}
catch (WebdavException e) {
throw e;
}
catch (SlideException e) {
int statusCode = getErrorCode( e );
sendError( statusCode, e );
throw new WebdavException( statusCode );
}
}
/**
* Get return status based on exception type.
*/
protected int getErrorCode(SlideException ex) {
try {
throw ex;
} catch(RevisionNotFoundException e) {
return WebdavStatus.SC_NOT_FOUND;
} catch (SlideException e) {
return super.getErrorCode(e);
}
}
/**
* Restores all live properties that should not be copied.
*
* @param destinationRevisionDescriptor the descriptor to restore.
* @param existingDestinationRevisionDescriptor the descriptor that has been overwritten.
*/
private void restoreLiveProperties(String destinationUri, NodeRevisionDescriptor destinationNrd, NodeRevisionDescriptor existingNrd) {
// remove all live properties
Enumeration propertyEnum = destinationNrd.enumerateProperties();
NodeProperty property = null;
while (propertyEnum.hasMoreElements()) {
property = (NodeProperty)propertyEnum.nextElement();
if (isLivePropertyToRestore(destinationUri, property)) {
destinationNrd.removeProperty(property);
}
}
// copy all live properties of the existing destination
propertyEnum = existingNrd.enumerateProperties();
property = null;
while (propertyEnum.hasMoreElements()) {
property = (NodeProperty)propertyEnum.nextElement();
if (isLivePropertyToRestore(destinationUri, property)) {
destinationNrd.setProperty(property);
}
}
}
/**
* Indicates if the given property is a live property to restore.
*
* @param property the NodeProperty to decide.
*
* @return <code>true</code> if this is a live property to restore.
*/
private boolean isLivePropertyToRestore(String uri, NodeProperty property) {
boolean isLivePropertyToRestore = /*property.isLiveProperty() &&*/ (
DeltavConstants.DELTAV_PROPERTY_LIST.contains(property.getName()) ||
AclConstants.ACL_PROPERTY_LIST.contains(property.getName()) ||
BindConstants.BIND_PROPERTY_LIST.contains(property.getName()) ||
P_CREATIONDATE.equals(property.getName()) ||
( P_DISPLAYNAME.equals(property.getName()) &&
Configuration.useBinding(token.getUri(slideToken, uri).getStore()) )
);
return isLivePropertyToRestore;
}
/**
* Sets all DeltaV specific properties of the given NodeRevisionDescriptor
* to their initial value.
*
* @param revisionDescriptor the NodeRevisionDescriptor whose DeltaV
* properties should be reset.
*/
private void resetDeltavProperties(NodeRevisionDescriptor revisionDescriptor, String resourcePath) {
// use initial values for DeltaV properties
PropertyHelper propertyHelper = PropertyHelper.getPropertyHelper(slideToken, token, getConfig());
ResourceKind resourceKind = VersionableImpl.getInstance();
Iterator initialPropertyIterator =
propertyHelper.createInitialProperties(resourceKind, resourcePath).iterator();
NodeProperty property = null;
List initialDeltavProperties = new ArrayList();
while (initialPropertyIterator.hasNext()) {
property = (NodeProperty)initialPropertyIterator.next();
if (DeltavConstants.DELTAV_PROPERTY_LIST.contains(property.getName())) {
initialDeltavProperties.add(property);
}
}
Enumeration propertyEnum = revisionDescriptor.enumerateProperties();
property = null;
int index = 0;
while (propertyEnum.hasMoreElements()) {
property = (NodeProperty)propertyEnum.nextElement();
if (DeltavConstants.DELTAV_PROPERTY_LIST.contains(property.getName())) {
index = initialDeltavProperties.indexOf(property);
if (index >= 0) {
revisionDescriptor.setProperty((NodeProperty)initialDeltavProperties.get(index));
}
else {
revisionDescriptor.removeProperty(property);
}
}
}
}
/**
* Restores the "backup" NodeRevisionDescriptor which has been saved in
* method {@link #beforeDelete beforeDelete()}.
*
* @param destinationUri the Uri of the resource.
* @param destinationRevisionDescriptors the NodeRevisionDescriptors of
* the resource.
*/
private void restoreBackupRevisionDescriptor(String destinationUri, NodeRevisionDescriptors destinationNrds) throws RevisionNotFoundException, ServiceAccessException, RevisionAlreadyExistException, ObjectNotFoundException, LinkedObjectNotFoundException, ObjectLockedException, AccessDeniedException, RevisionDescriptorNotFoundException, BranchNotFoundException, NodeNotVersionedException, VetoException {
NodeRevisionDescriptor backupNrd =
(NodeRevisionDescriptor)destinationBackupDescriptorMap.get(destinationUri);
if (backupNrd != null) {
try {
content.retrieve( slideToken,
destinationNrds,
NodeRevisionNumber.HIDDEN_0_0 );
content.store( slideToken,
destinationNrds.getUri(),
backupNrd,
null );
}
catch (RevisionDescriptorNotFoundException e) {
content.create( slideToken,
destinationNrds.getUri(),
null,
backupNrd,
null ); // branch=null, revisionContent=null
}
}
}
// ------------------------------------------------------ Interface CopyRouteRedirector
/**
* Returns the (redirected) CopyRoute to use. Must not be <code>null</code>.
*
* @param the original CopyRoute.
*
* @return the (redirected) CopyRoute to use.
*
* @throws SlideException this Exception will be passed to the caller
* of the Macro helper (contained in the
* MacroCopyException).
*/
public CopyRoute getRedirectedCopyRoute(CopyRoute copyRoute) throws SlideException {
if (Configuration.useVersionControl()) {
String sourceUri = copyRoute.getSourceUri();
String destinationUri = copyRoute.getDestinationUri();
try {
sourceUri = versioningHelper.getLabeledResourceUri(sourceUri, labelHeader);
copyRoute = new CopyRoute(sourceUri, destinationUri);
}
catch (LabeledRevisionNotFoundException e) {
ViolatedPrecondition violatedPrecondition =
new ViolatedPrecondition(DeltavConstants.C_MUST_SELECT_VERSION_IN_HISTORY,
WebdavStatus.SC_CONFLICT);
throw new PreconditionViolationException(violatedPrecondition, sourceUri);
}
}
return copyRoute;
}
// ------------------------------------------------------ Interface CopyListener
/**
* This method is called prior to copying the resource associated by
* the given <code>sourceUri</code>. The copy can be prohibited by
* throwing a SlideException.
*
* @param sourceUri the Uri of the resource that will be copied.
* @param destinationUri the Uri of the copy.
*
* @throws SlideException this Exception will be passed to the caller
* of the Macro helper (contained in the
* MacroDeleteException.
*/
public void beforeCopy(String sourceUri, String destinationUri, boolean isRootOfCopy) throws SlideException {
if (DetailedWebdavEvent.COPY_BEFORE_COPY.isEnabled()) {
EventDispatcher.getInstance().fireVetoableEvent(
DetailedWebdavEvent.COPY_BEFORE_COPY,
new DetailedWebdavEvent(this, destinationUri, sourceUri));
}
if(Configuration.useVersionControl()) {
UriHandler sourceUh = UriHandler.getUriHandler(sourceUri);
if (sourceUh.isHistoryUri()) {
throw new PreconditionViolationException(
new ViolatedPrecondition(DeltavConstants.C_CANNOT_COPY_HISTORY, WebdavStatus.SC_FORBIDDEN), sourceUri);
}
if (!macroParameters.isDeleteCreate()) {
beforeUpdateOrDelete( destinationUri );
}
}
if (isRootOfCopy && Configuration.useBinding(token.getUri(slideToken, destinationUri).getStore())) {
// collect the parent bindings of the destination node
Map parentBindings = new HashMap();
try {
NodeRevisionDescriptor destinationNrd =
content.retrieve( slideToken, content.retrieve(slideToken, destinationUri) );
XMLValue v = new XMLValue( (String)destinationNrd.getProperty(PN_PARENT_SET).getValue());
Iterator i = v.iterator();
while (i.hasNext()) {
Namespace dnsp = Namespace.getNamespace(S_DAV);
Element parentElm = (Element)i.next();
String segment = parentElm.getChild(E_SEGMENT, dnsp).getTextTrim();
String href = parentElm.getChild(E_HREF, dnsp).getTextTrim();
parentBindings.put( href, segment );
}
}
catch( ServiceAccessException x ) {
throw x;
}
catch (SlideException e) {}
catch (JDOMException e) {}
macroParameters.setParameter( Macro.PARENT_BINDINGS, parentBindings );
}
}
/**
* This method is called after copying the resource to
* the given <code>destinationUri</code>.
*
* @param sourceUri the Uri of the resource that has been copied.
* @param destinationUri the Uri of the copy.
*
* @throws SlideException this Exception will be passed to the caller
* of the Macro helper (contained in the
* MacroDeleteException.
*/
public void afterCopy(String sourceUri, String destinationUri, boolean isRootOfCopy, boolean destinationExists) throws SlideException {
if(Configuration.useVersionControl()) {
NodeRevisionDescriptors destinationNrds = content.retrieve( slideToken, destinationUri);
NodeRevisionDescriptor destinationNrd = content.retrieve( slideToken, destinationNrds);
// restore backup descriptor
restoreBackupRevisionDescriptor(destinationUri, destinationNrds);
NodeRevisionDescriptor existingNrd =
(NodeRevisionDescriptor)destinationDescriptorMap.get(destinationUri);
if (existingNrd != null) {
// there has been an existing destination, so restore live properties
restoreLiveProperties(destinationUri, destinationNrd, existingNrd);
}
else {
// DAV:must-not-copy-versioning-property
resetDeltavProperties(destinationNrd, destinationUri);
}
// set <workspace> property
versioningHelper.setWorkspaceProperty(destinationUri, destinationNrd);
// set some other properties
destinationNrd.setLastModified( new Date() ); // P_GETLASTMODIFIED
destinationNrd.setETag( PropertyHelper.computeEtag(destinationUri, destinationNrd) ); // P_GETETAG
if (!destinationExists) {
// copy is creating a new resource
String creator = ((SubjectNode)security.getPrincipal(slideToken)).getPath().lastSegment();
destinationNrd.setOwner(creator);
}
content.store(slideToken, destinationNrds.getUri(), destinationNrd, null);
// checkin if necessary
boolean mustCheckin = versioningHelper.mustCheckinAutoVersionedVCR(slideToken, destinationNrds, destinationNrd);
if (mustCheckin) {
try {
versioningHelper.checkin(destinationUri, false, false, true ); //forkOk=false, keepCheckedOut=false
}
catch (IOException e) {
throw new SlideException("Checkin failed: " + e.getMessage());
}
catch (JDOMException e) {
throw new SlideException("Checkin failed: " + e.getMessage());
}
}
// check if the resource should be put under version-control
if( isAutoVersionControl(destinationUri) && !isCollection(destinationUri) && !isExcludedForVersionControl(destinationUri) ) {
versioningHelper.versionControl(destinationUri);
}
}
if (isRootOfCopy && Configuration.useBinding(token.getUri(slideToken, destinationUri).getStore())) {
// try to restore the parent bindings
if (macroParameters.getParameter(Macro.PARENT_BINDINGS) != null) {
Map parentBindings = (Map)macroParameters.getParameter(Macro.PARENT_BINDINGS);
Iterator i = parentBindings.entrySet().iterator();
while (i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
ObjectNode parentNode = structure.retrieve( slideToken, (String)me.getKey() );
ObjectNode destinationNode = structure.retrieve( slideToken, destinationUri );
String segment = (String)me.getValue();
structure.addBinding( slideToken, parentNode, segment, destinationNode );
}
}
}
if (DetailedWebdavEvent.COPY_AFTER_COPY.isEnabled()) {
EventDispatcher.getInstance().fireVetoableEvent(
DetailedWebdavEvent.COPY_AFTER_COPY,
new DetailedWebdavEvent(this, destinationUri, sourceUri));
}
}
// ------------------------------------------------------ Interface DeleteListener
/**
* This method is called prior to deleting the resource associated by
* the given <code>targetUri</code>. The deletion can be prohibited by
* throwing a SlideException.
*
* @param destinationUri the Uri of the resource that will be deleted.
*
* @throws SlideException this Exception will be passed to the caller
* of the Macro helper (contained in the
* MacroDeleteException.
*/
public void beforeDelete(String destinationUri) throws SlideException {
if (DetailedWebdavEvent.COPY_BEFORE_DELETE.isEnabled()) {
EventDispatcher.getInstance().fireVetoableEvent(
DetailedWebdavEvent.COPY_BEFORE_DELETE,
new DetailedWebdavEvent(this, destinationUri, sourceUri));
}
beforeUpdateOrDelete( destinationUri );
}
/**
* This method is called prior to deleting the resource associated by
* the given <code>targetUri</code>. The deletion can be prohibited by
* throwing a SlideException.
*
* @param destinationUri the Uri of the resource that will be deleted.
*
* @throws SlideException this Exception will be passed to the caller
* of the Macro helper (contained in the
* MacroDeleteException.
*/
private void beforeUpdateOrDelete(String destinationUri) throws SlideException {
if( Configuration.useVersionControl() ) {
NodeRevisionDescriptors destinationNrds = null;
NodeRevisionDescriptor destinationNrd = null;
try {
destinationNrds = content.retrieve( slideToken, destinationUri);
destinationNrd = content.retrieve( slideToken, destinationNrds);
}
catch (ObjectNotFoundException e) {}
if (destinationNrds != null && destinationNrd != null) {
ResourceKind resourceKind = AbstractResourceKind.determineResourceKind(token, destinationUri, destinationNrd);
if (resourceKind instanceof CheckedInVersionControlled) {
// check precondition DAV:cannot-modify-version-controlled-content
String autoVersion = versioningHelper.getAutoVersionElementName(destinationNrd);
if (autoVersion == null) {
autoVersion = "";
}
if ( !E_CHECKOUT_CHECKIN.equals(autoVersion) &&
!E_CHECKOUT_UNLOCKED_CHECKIN.equals(autoVersion) &&
!E_CHECKOUT.equals(autoVersion) &&
!E_CHECKOUT_IGNORE_UNLOCK.equals(autoVersion) &&
!E_LOCKED_CHECKOUT.equals(autoVersion) ) {
throw new PreconditionViolationException(new ViolatedPrecondition(C_CANNOT_MODIFY_VERSION_CONTROLLED_CONTENT,
WebdavStatus.SC_FORBIDDEN), destinationUri);
}
if ( E_LOCKED_CHECKOUT.equals(autoVersion) &&
( !versioningHelper.isWriteLocked(slideToken, destinationNrds) ) ) {
throw new PreconditionViolationException(new ViolatedPrecondition(C_CANNOT_MODIFY_VERSION_CONTROLLED_CONTENT,
WebdavStatus.SC_FORBIDDEN), destinationUri);
}
}
// check precondition DAV:cannot-modify-version
UriHandler uriHandler = UriHandler.getUriHandler(destinationUri);
if (uriHandler.isVersionUri()) {
throw new PreconditionViolationException(new ViolatedPrecondition(C_CANNOT_MODIFY_VERSION,
WebdavStatus.SC_FORBIDDEN), destinationUri);
}
// checkout if necessary
if( Configuration.useVersionControl() &&
(resourceKind instanceof CheckedInVersionControlled) &&
versioningHelper.mustCheckoutAutoVersionedVCR(destinationNrds, destinationNrd) ) {
try {
versioningHelper.checkout(destinationNrds, destinationNrd, false, false, true );
}
catch (IOException e) {
throw new SlideException("Checkout failed: " + e.getMessage());
}
catch (JDOMException e) {
throw new SlideException("Checkout failed: " + e.getMessage());
}
}
// store the descriptor(s) in order to restore it in afterDelete()
// (the COPY specification for DeltaV says that an existing destination
// must not be deleted)
try {
NodeRevisionDescriptor backupNrd =
content.retrieve( slideToken, destinationNrds, NodeRevisionNumber.HIDDEN_0_0 );
destinationBackupDescriptorMap.put(destinationUri, backupNrd);
}
catch (RevisionDescriptorNotFoundException e) {
}
destinationDescriptorMap.put(destinationUri, destinationNrd);
}
}
}
/**
* This method is called after deleting the resource associated by
* the given <code>targetUri</code>.
*
* @param targetUri the Uri of the resource that has been deleted.
*
* @throws SlideException this Exception will be passed to the caller
* of the Macro helper (contained in the
* targetUricroDeleteException.
*/
public void afterDelete(String targetUri) throws SlideException {
if (DetailedWebdavEvent.COPY_AFTER_DELETE.isEnabled()) {
EventDispatcher.getInstance().fireVetoableEvent(
DetailedWebdavEvent.COPY_AFTER_DELETE,
new DetailedWebdavEvent(this, destinationUri, sourceUri));
}
}
}
The table below shows all metrics for CopyMethod.java.




