@Override
    public Path copy(final Path source, final Path copy, final TransferStatus status, final ConnectionCallback callback, final StreamListener listener) throws BackgroundException {
        try {
            final String target = new DefaultUrlProvider(session.getHost()).toUrl(copy).find(DescriptiveUrl.Type.provider).getUrl();
            if(session.getFeature(Lock.class) != null && status.getLockId() != null) {
                // Indicate that the client has knowledge of that state token
                session.getClient().copy(new DAVPathEncoder().encode(source), target, status.isExists(),
                        Collections.singletonMap(HttpHeaders.IF, String.format("(<%s>)", status.getLockId())));
            }
            else {
                session.getClient().copy(new DAVPathEncoder().encode(source), target, status.isExists());
            }
            listener.sent(status.getLength());
            return copy.withAttributes(source.attributes());
        }
        catch(SardineException e) {
            throw new DAVExceptionMappingService().map("Cannot copy {0}", e, source);
        }
        catch(IOException e) {
            throw new HttpExceptionMappingService().map(e, source);
        }
    }
@Test
    public void testCopyDirectory() throws Exception {
        final Path directory = new Path(new DefaultHomeFinderService(session).find(), new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.directory));
        final String name = new AlphanumericRandomStringService().random();
        final Path file = new Path(directory, name, EnumSet.of(Path.Type.file));
        new DAVDirectoryFeature(session).mkdir(directory, new TransferStatus());
        new DAVTouchFeature(session).touch(file, new TransferStatus());
        final Path copy = new Path(new DefaultHomeFinderService(session).find(), new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.directory));
        new DAVDirectoryFeature(session).mkdir(copy, new TransferStatus());
        assertThrows(ConflictException.class, () -> new DAVCopyFeature(session).copy(directory, copy, new TransferStatus().exists(false), new DisabledConnectionCallback(), new DisabledStreamListener()));
        new DAVCopyFeature(session).copy(directory, copy, new TransferStatus().exists(true), new DisabledConnectionCallback(), new DisabledStreamListener());
        assertTrue(new DAVFindFeature(session).find(file));
        assertTrue(new DAVFindFeature(session).find(copy));
        assertTrue(new DAVFindFeature(session).find(new Path(copy, name, EnumSet.of(Path.Type.file))));
        new DAVDeleteFeature(session).delete(Arrays.asList(copy, directory), new DisabledLoginCallback(), new Delete.DisabledCallback());
    }