package er.attachment.upload; import java.io.File; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.webobjects.eocontrol.EOEditingContext; import com.webobjects.eocontrol.EOGlobalID; import er.attachment.model.ERAttachment; import er.attachment.processors.ERAttachmentProcessor; import er.extensions.concurrency.ERXAsyncQueue; import er.extensions.eof.ERXEC; import er.extensions.foundation.ERXExceptionUtilities; /** * The <code>ERAttachmentUploadQueue</code> is a queue to upload attachments. * <p> * Only <code>ERRemoteAttachment</code>s can be upload using this queue. * * @author <a href="mailto:hprange@gmail.com.br">Henrique Prange</a> * * @param <T> * the type of the attachment that can queued for uploading. * * @see ERRemoteAttachment */ public abstract class ERAttachmentUploadQueue<T extends ERAttachment & ERRemoteAttachment> extends ERXAsyncQueue<ERAttachmentQueueEntry<T>> { protected final ERAttachmentProcessor<T> _processor; private static final Logger log = LoggerFactory.getLogger(ERAttachmentProcessor.class); public ERAttachmentUploadQueue(String name, ERAttachmentProcessor<T> processor) { super(name); _processor = processor; } /** * Adds an attachment to the end of the queue. * * @param attachment * the attachment to upload */ public void enqueue(T attachment) { EOEditingContext editingContext = attachment.editingContext(); editingContext.lock(); try { EOGlobalID attachmentID = editingContext.globalIDForObject(attachment); ERAttachmentQueueEntry<T> entry = new ERAttachmentQueueEntry<>(attachment._pendingUploadFile(), attachmentID); enqueue(entry); } finally { editingContext.unlock(); } } @Override public void process(ERAttachmentQueueEntry<T> entry) { EOEditingContext editingContext = ERXEC.newEditingContext(); T attachment = entry.attachment(editingContext); File uploadedFile = entry.uploadedFile(); if (uploadedFile != null && uploadedFile.exists()) { try { performUpload(editingContext, attachment, uploadedFile); editingContext.lock(); try { attachment.setAvailable(Boolean.TRUE); editingContext.saveChanges(); } finally { editingContext.unlock(); } if (_processor.delegate() != null) { _processor.delegate().attachmentAvailable(_processor, attachment); } } catch (Throwable t) { if (_processor.delegate() != null) { _processor.delegate().attachmentNotAvailable(_processor, attachment, ERXExceptionUtilities.toParagraph(t)); } log.error("Failed to upload '{}' to the remote server.", uploadedFile, t); } finally { if (attachment._isPendingDelete()) { uploadedFile.delete(); } } } else { if (_processor.delegate() != null) { _processor.delegate().attachmentNotAvailable(_processor, attachment, "Missing attachment file '" + uploadedFile + "'."); } log.error("Missing attachment file '{}'.", uploadedFile); } } /** * Perform the upload of the attachment to the remote server. * * @param attachment * the attachment to upload * @param uploadedFile * the file to upload */ protected abstract void performUpload(EOEditingContext editingContext, T attachment, File uploadedFile) throws Exception; }