package com.bradmcevoy.http.webdav; import com.bradmcevoy.http.*; import com.bradmcevoy.http.Request.Method; import com.bradmcevoy.http.exceptions.BadRequestException; import com.bradmcevoy.http.exceptions.ConflictException; import com.bradmcevoy.http.exceptions.NotAuthorizedException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.URI; public class CopyHandler implements ExistingEntityHandler { private Logger log = LoggerFactory.getLogger( CopyHandler.class ); private final WebDavResponseHandler responseHandler; private final HandlerHelper handlerHelper; private final ResourceHandlerHelper resourceHandlerHelper; private DeleteHelper deleteHelper; private boolean deleteExistingBeforeCopy = true; public CopyHandler( WebDavResponseHandler responseHandler, HandlerHelper handlerHelper, ResourceHandlerHelper resourceHandlerHelper ) { this.responseHandler = responseHandler; this.handlerHelper = handlerHelper; this.resourceHandlerHelper = resourceHandlerHelper; this.deleteHelper = new DeleteHelperImpl( handlerHelper ); } public String[] getMethods() { return new String[]{Method.COPY.code}; } public boolean isCompatible( Resource handler ) { return ( handler instanceof CopyableResource ); } public void processResource( HttpManager manager, Request request, Response response, Resource r ) throws NotAuthorizedException, ConflictException, BadRequestException { resourceHandlerHelper.processResource( manager, request, response, r, this ); } public void process( HttpManager httpManager, Request request, Response response ) throws ConflictException, NotAuthorizedException, BadRequestException { resourceHandlerHelper.process( httpManager, request, response, this ); } public void processExistingResource( HttpManager manager, Request request, Response response, Resource resource ) throws NotAuthorizedException, BadRequestException, ConflictException { CopyableResource r = (CopyableResource) resource; String sDest = request.getDestinationHeader(); // sDest = HttpManager.decodeUrl(sDest); URI destUri = URI.create( sDest ); sDest = destUri.getPath(); Dest dest = new Dest( destUri.getHost(), sDest ); Resource rDest = manager.getResourceFactory().getResource( dest.host, dest.url ); log.debug( "process: copying from: " + r.getName() + " -> " + dest.url + "/" + dest.name ); if( rDest == null ) { log.debug( "process: destination parent does not exist: " + sDest ); responseHandler.respondConflict( resource, response, request, "Destination does not exist: " + sDest ); } else if( !( rDest instanceof CollectionResource ) ) { log.debug( "process: destination exists but is not a collection" ); responseHandler.respondConflict( resource, response, request, "Destination exists but is not a collection: " + sDest ); } else { log.debug( "process: copy resource to: " + rDest.getName() ); Resource fDest = manager.getResourceFactory().getResource( dest.host, dest.url + "/" + dest.name ); if( handlerHelper.isLockedOut( request, fDest ) ) { responseHandler.respondLocked( request, response, resource ); return ; } else { CollectionResource colDest = (CollectionResource) rDest; Resource rExisting = colDest.child( dest.name ); if( rExisting != null ) { Boolean overwrite = request.getOverwriteHeader(); if( overwrite != null && overwrite.booleanValue() ) { // Exists, and overwrite = F, disallow - http://www.webdav.org/specs/rfc4918.html#rfc.section.9.8.4 responseHandler.respondPreconditionFailed( request, response, resource ); return; } else { // Overwrite is absent or T, so continue if( deleteHelper.isLockedOut( request, rExisting ) ) { log.info( "copy destination exists but is locked" ); responseHandler.respondPreconditionFailed( request, response, resource ); return; } else { if( deleteExistingBeforeCopy ) { if( rExisting instanceof DeletableResource ) { log.debug( "copy destination exists and is deletable, delete it.."); DeletableResource dr = (DeletableResource) rExisting; deleteHelper.delete( dr ); } else { log.warn( "copy destination exists and is a collection so must be deleted, but does not implement: " + DeletableResource.class ); responseHandler.respondConflict( rExisting, response, request, sDest ); return; } } } } } r.copyTo( colDest, dest.name ); responseHandler.respondCreated( resource, response, request ); } } } public void setDeleteExistingBeforeCopy( boolean deleteExistingBeforeCopy ) { this.deleteExistingBeforeCopy = deleteExistingBeforeCopy; } public boolean isDeleteExistingBeforeCopy() { return deleteExistingBeforeCopy; } }