@Override
    protected void onRun() throws Exception {
      // TODO: When the rest of storage is rewritten using TransactionRunnable,
      //       this method should be disolved.

      final Session session = this.context.getWiki().getHibernateStore().getSession(this.context);

      // Delete the content from the attachment.
      // In case it was stored in the database by XWikiHibernateAttachmentStore.
      session.delete(new XWikiAttachmentContent(this.attachment));

      // Update the document if required.
      if (this.updateDocument) {
        final String filename = this.attachment.getFilename();
        final List<XWikiAttachment> list = attachment.getDoc().getAttachmentList();
        for (int i = 0; i < list.size(); i++) {
          if (filename.equals(list.get(i).getFilename())) {
            list.remove(i);
            break;
          }
        }
        this.context
            .getWiki()
            .getStore()
            .saveXWikiDoc(this.attachment.getDoc(), this.context, false);
      }

      // Delete the attachment metadata.
      session.delete(this.attachment);
    }
 /**
  * Make sure the attachment is associated with a document.
  *
  * @param attachment the attachment to check.
  * @throws IllegalArgumentException if attachment.getDoc() yields null.
  */
 private static void checkAttachedToDocument(final XWikiAttachment attachment) {
   if (attachment.getDoc() == null) {
     throw new IllegalArgumentException(
         "In order to use this function, the attachment ["
             + attachment.getFilename()
             + "] must be associated with a document.");
   }
 }
    /**
     * Construct a TransactionRunnable for saving the attachment content.
     *
     * @param attachment the XWikiAttachment whose content should be saved.
     * @param updateDocument whether or not to update the document at the same time.
     * @param context the XWikiContext for the request.
     * @param attachFile the File to store the attachment in.
     * @param tempFile the File to put the attachment content in until the transaction is complete.
     * @param backupFile the File to backup the content of the existing attachment in.
     * @param lock this Lock will be locked while the attachment file is being written to.
     * @throws XWikiException if thrown by {@link XWikiAttachment#updateContentArchive(XWikiContext)}
     * or {@link FilesystemAttachmentVersioningStore#
     * getArchiveSaveRunnable(XWikiAttachmentArchive, XWikiContext)
     */
    AttachmentSaveTransactionRunnable(
        final XWikiAttachment attachment,
        final boolean updateDocument,
        final XWikiContext context,
        final File attachFile,
        final File tempFile,
        final File backupFile,
        final ReadWriteLock lock)
        throws XWikiException {
      final StreamProvider provider = new AttachmentContentStreamProvider(attachment, context);
      new FileSaveTransactionRunnable(attachFile, tempFile, backupFile, lock, provider).runIn(this);

      // If the versioning store supports TransactionRunnable then use it, otherwise don't.
      final AttachmentVersioningStore avs = context.getWiki().getAttachmentVersioningStore();
      final XWikiAttachmentArchive archive = attachment.getAttachment_archive();
      if (avs instanceof FilesystemAttachmentVersioningStore) {
        final FilesystemAttachmentVersioningStore favs = (FilesystemAttachmentVersioningStore) avs;

        // If first save then create a new archive.
        if (archive == null) {
          favs.getArchiveSaveRunnable(new ListAttachmentArchive(attachment), context).runIn(this);
        } else {
          favs.getArchiveSaveRunnable(archive, context).runIn(this);
        }
      } else {
        new TransactionRunnable<XWikiHibernateTransaction>() {
          protected void onRun() throws XWikiException {
            avs.saveArchive(archive, context, false);
          }
        }.runIn(this);
      }

      // If updating of the parent document is required then add a TransactionRunnable to do that.
      if (updateDocument) {
        final XWikiStoreInterface store = context.getWiki().getStore();
        final XWikiDocument doc = attachment.getDoc();
        new TransactionRunnable<XWikiHibernateTransaction>() {
          protected void onRun() throws XWikiException {
            store.saveXWikiDoc(doc, context, false);
          }
        }.runIn(this);
      }

      this.attachment = attachment;
      this.updateDocument = updateDocument;
      this.context = context;
    }