package er.attachment.processors; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import com.webobjects.appserver.WOContext; import com.webobjects.appserver.WORequest; import com.webobjects.eocontrol.EOEditingContext; import com.webobjects.foundation.NSTimestamp; import er.attachment.model.ERFileAttachment; import er.extensions.foundation.ERXFileUtilities; import er.extensions.foundation.ERXProperties; /** * ERFileAttachmentProcessor implements storing attachments as files on the system that are either served * via a proxy request handler or directly by the webserver. For more information about configuring * an ERFileAttachmentProcessor, see the top level documentation. * * @property er.attachment.[configurationName].file.proxy * @property er.attachment.file.proxy * @property er.attachment.[configurationName].file.overwrite * @property er.attachment.file.overwrite * @property er.attachment.[configurationName].file.filesystemPath * @property er.attachment.file.filesystemPath * @property er.attachment.[configurationName].file.webPath * @property er.attachment.file.webPath * * @author mschrag */ public class ERFileAttachmentProcessor extends ERAttachmentProcessor<ERFileAttachment> { @Override public ERFileAttachment _process(EOEditingContext editingContext, File uploadedFile, String recommendedFileName, String mimeType, String configurationName, String ownerID, boolean pendingDelete) throws IOException { boolean proxy = true; String proxyStr = ERXProperties.stringForKey("er.attachment." + configurationName + ".file.proxy"); if (proxyStr == null) { proxyStr = ERXProperties.stringForKey("er.attachment.file.proxy"); } if (proxyStr != null) { proxy = Boolean.parseBoolean(proxyStr); } boolean overwrite = false; String overwriteStr = ERXProperties.stringForKey("er.attachment." + configurationName + ".file.overwrite"); if (overwriteStr == null) { overwriteStr = ERXProperties.stringForKey("er.attachment.file.overwrite"); } if (overwriteStr != null) { overwrite = Boolean.parseBoolean(overwriteStr); } String filesystemPath = ERXProperties.stringForKey("er.attachment." + configurationName + ".file.filesystemPath"); if (filesystemPath == null) { filesystemPath = ERXProperties.stringForKey("er.attachment.file.filesystemPath"); } if (filesystemPath == null) { throw new IllegalArgumentException("There is no 'er.attachment." + configurationName + ".file.filesystemPath' or 'er.attachment.file.filesystemPath' property set."); } if (!filesystemPath.contains("${")) { filesystemPath = filesystemPath + "/attachments/${hash}/${pk}${ext}"; } String webPath = ERXProperties.stringForKey("er.attachment." + configurationName + ".file.webPath"); if (webPath == null) { webPath = ERXProperties.stringForKey("er.attachment.file.webPath"); } if (webPath == null) { if (!proxy) { throw new IllegalArgumentException("There is no 'er.attachment." + configurationName + ".file.webPath' or 'er.attachment.file.webPath' property set."); } webPath = "/${pk}${ext}"; } else if (!webPath.startsWith("/")) { webPath = "/" + webPath; } ERFileAttachment attachment = ERFileAttachment.createERFileAttachment(editingContext, Boolean.TRUE, new NSTimestamp(), mimeType, recommendedFileName, Boolean.valueOf(proxy), Integer.valueOf((int) uploadedFile.length()), webPath); if (delegate() != null) { delegate().attachmentCreated(this, attachment); } try { webPath = ERAttachmentProcessor._parsePathTemplate(attachment, webPath, recommendedFileName); filesystemPath = ERAttachmentProcessor._parsePathTemplate(attachment, filesystemPath, recommendedFileName); File desiredFilesystemPath = new File(filesystemPath); File actualFilesystemPath = ERXFileUtilities.reserveUniqueFile(desiredFilesystemPath, overwrite); ERXFileUtilities.copyFileToFile(uploadedFile, actualFilesystemPath, pendingDelete, true); String desiredFileName = desiredFilesystemPath.getName(); String actualFileName = actualFilesystemPath.getName(); // in case the name was not unique and changed, we need to update webPath ... webPath = webPath.replaceAll("\\Q" + desiredFileName + "\\E$", actualFileName); attachment.setWebPath(webPath); attachment.setFilesystemPath(actualFilesystemPath.getAbsolutePath()); if (delegate() != null) { delegate().attachmentAvailable(this, attachment); } } catch (IOException e) { attachment.delete(); throw e; } catch (RuntimeException e) { attachment.delete(); throw e; } return attachment; } @Override public InputStream attachmentInputStream(ERFileAttachment attachment) throws IOException { return new FileInputStream(new File(attachment.filesystemPath())); } @Override public String attachmentUrl(ERFileAttachment attachment, WORequest request, WOContext context) { String attachmentUrl; if (!attachment.proxied().booleanValue()) { attachmentUrl = attachment.webPath(); } else { attachmentUrl = proxiedUrl(attachment, context); } return attachmentUrl; } @Override public void deleteAttachment(ERFileAttachment attachment) throws IOException { String filesystemPath = attachment.filesystemPath(); File attachmentFile = new File(filesystemPath); if (attachmentFile.exists() && !attachmentFile.delete()) { throw new IOException("Failed to delete the attachment '" + attachmentFile + "'."); } } }