@Override
    public List<MultipartUpload> find(final Path file) throws BackgroundException {
        if(log.isDebugEnabled()) {
            log.debug(String.format("Finding multipart uploads for %s", file));
        }
        final List<MultipartUpload> uploads = new ArrayList<>();
        // This operation lists in-progress multipart uploads. An in-progress multipart upload is a
        // multipart upload that has been initiated, using the Initiate Multipart Upload request, but has
        // not yet been completed or aborted.
        String nextUploadIdMarker = null;
        String nextKeyMarker = null;
        boolean isTruncated;
        do {
            final Path bucket = containerService.getContainer(file);
            final MultipartUploadChunk chunk;
            try {
                chunk = session.getClient().multipartListUploadsChunked(
                        bucket.isRoot() ? StringUtils.EMPTY : bucket.getName(), containerService.getKey(file),
                        String.valueOf(Path.DELIMITER), nextKeyMarker, nextUploadIdMarker, null, false);
            }
            catch(S3ServiceException e) {
                final BackgroundException failure = new S3ExceptionMappingService().map("Upload {0} failed", e, file);
                if(failure instanceof NotfoundException) {
                    return Collections.emptyList();
                }
                if(failure instanceof InteroperabilityException) {
                    return Collections.emptyList();
                }
                throw failure;
            }
            uploads.addAll(Arrays.asList(chunk.getUploads()));
            if(log.isInfoEnabled()) {
                log.info(String.format("Found %d previous multipart uploads for %s", uploads.size(), file));
            }
            // Sort with newest upload first in list
            uploads.sort(new Comparator<MultipartUpload>() {
                @Override
                public int compare(final MultipartUpload o1, final MultipartUpload o2) {
                    return -o1.getInitiatedDate().compareTo(o2.getInitiatedDate());
                }
            });
            nextKeyMarker = chunk.getPriorLastKey();
            nextUploadIdMarker = chunk.getPriorLastIdMarker();
            isTruncated = !chunk.isListingComplete();
        }
        while(isTruncated && nextUploadIdMarker != null);
        if(log.isInfoEnabled()) {
            for(MultipartUpload upload : uploads) {
                log.info(String.format("Found multipart upload %s for %s", upload, file));
            }
        }
        return uploads;
    }
@Test
    public void testFind() throws Exception {
        final Path container = new Path("test-eu-central-1-cyberduck", EnumSet.of(Path.Type.directory, Path.Type.volume));
        final S3AccessControlListFeature acl = new S3AccessControlListFeature(session);
        final Path directory = new S3DirectoryFeature(session, new S3WriteFeature(session, acl), acl).mkdir(
                new Path(container, new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.directory)), new TransferStatus());
        final S3DefaultMultipartService service = new S3DefaultMultipartService(session);
        assertTrue(service.find(directory).isEmpty());
        final Path file = new Path(directory, new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.file));
        final S3Object object = new S3WriteFeature(session, acl).getDetails(file, new TransferStatus());
        final MultipartUpload first = session.getClient().multipartStartUpload(container.getName(), object);
        assertNotNull(first);
        assertFalse(service.find(directory).isEmpty());
        assertTrue(service.find(new Path(container, new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.directory))).isEmpty());
        assertEquals(first.getUploadId(), service.find(directory).iterator().next().getUploadId());
        assertFalse(new S3FindFeature(session, acl).find(file));
        final Path upload = new S3ListService(session, acl).list(directory, new DisabledListProgressListener()).find(new SimplePathPredicate(file));
        assertNotNull(upload);
        assertTrue(new S3FindFeature(session, acl).find(upload));
        assertTrue(upload.getType().contains(Path.Type.upload));
        assertTrue(new S3FindFeature(session, acl).find(upload));
        assertNotEquals(PathAttributes.EMPTY, new S3AttributesFinderFeature(session, acl).find(upload));
        // Make sure timestamp is later.
        Thread.sleep(2000L);
        final MultipartUpload second = session.getClient().multipartStartUpload(container.getName(), object);
        assertNotNull(second);
        final MultipartUpload multipart = service.find(file).iterator().next();
        assertNotNull(multipart);
        assertEquals(second.getUploadId(), multipart.getUploadId());
        assertNotNull(multipart);
        service.delete(first);
        service.delete(second);
        new S3DefaultDeleteFeature(session).delete(Collections.singletonList(directory), new DisabledLoginCallback(), new Delete.DisabledCallback());
    }