@Override
  public TransactionRunnable getAttachmentArchiveDeleteRunnable(final AttachmentReference ref) {
    final AttachmentFileProvider provider = this.fileTools.getAttachmentFileProvider(ref);
    final TransactionRunnable out = new TransactionRunnable();
    final File archiveMeta = provider.getAttachmentVersioningMetaFile();

    final Serializer<List<XWikiAttachment>, List<XWikiAttachment>> mSerializer =
        this.metaSerializer;

    (new TransactionRunnable() {
          @Override
          protected void onRun() throws IOException {
            if (archiveMeta.exists()) {
              InputStream is = null;
              try {
                is = new FileInputStream(archiveMeta);
                for (final XWikiAttachment ver : mSerializer.parse(is)) {
                  provider.getAttachmentVersionContentFile(ver.getVersion()).delete();
                }
              } finally {
                IOUtils.closeQuietly(is);
              }
            }
          }
        })
        .runIn(out);

    this.fileTools.getDeleter(provider.getAttachmentVersioningMetaFile()).runIn(out);

    return out;
  }
  @Override
  public TransactionRunnable getAttachmentArchiveSaveRunnable(final List versionList) {
    // For some reason this is required even though the interface specifies a
    // List<XWikiAttachment>, this appears to be a bug in javac.
    final List<XWikiAttachment> versions = (List<XWikiAttachment>) versionList;

    final TransactionRunnable out = new TransactionRunnable();

    if (versions.size() == 0) {
      return out;
    }

    final AttachmentReference ref = AttachmentTools.referenceForAttachment(versions.get(0));
    final AttachmentFileProvider provider = this.fileTools.getAttachmentFileProvider(ref);

    for (final XWikiAttachment attachVer : versions) {
      final String verName = attachVer.getVersion();
      // If the content is not dirty and the file was already saved then we will not update.
      if (attachVer.isContentDirty()
          || !provider.getAttachmentVersionContentFile(verName).exists()) {
        this.fileTools
            .getSaver(
                new AttachmentContentStreamProvider(attachVer.getAttachment_content()),
                provider.getAttachmentVersionContentFile(verName))
            .runIn(out);
      }
    }

    // Then do the metadata.
    final StreamProvider sp =
        new SerializationStreamProvider<List<XWikiAttachment>>(this.metaSerializer, versions);
    this.fileTools.getSaver(sp, provider.getAttachmentVersioningMetaFile()).runIn(out);

    return out;
  }
  @Override
  public TransactionRunnable getAttachmentArchiveLoadRunnable(
      final AttachmentReference ref, final List output) {
    final AttachmentFileProvider provider = this.fileTools.getAttachmentFileProvider(ref);
    final File metaFile = provider.getAttachmentVersioningMetaFile();

    // If no meta file then assume no archive and do nothing.
    if (!metaFile.exists()) {
      return new TransactionRunnable();
    }

    final Serializer<List<XWikiAttachment>, List<XWikiAttachment>> mSerializer =
        this.metaSerializer;

    return new TransactionRunnable() {
      @Override
      protected void onRun() throws IOException {
        final InputStream is = new FileInputStream(metaFile);
        final List<XWikiAttachment> attachList = mSerializer.parse(is);
        is.close();
        for (XWikiAttachment attach : attachList) {
          attach.setAttachment_content(
              new FilesystemAttachmentContent(
                  provider.getAttachmentVersionContentFile(attach.getVersion()), attach));
          output.add(attach);
        }
        // final ListAttachmentArchive out = new ListAttachmentArchive(attachList);
        // out.setAttachment(attachment);
        // attachment.setAttachment_archive(out);
      }
    };
  }