package er.attachment.metadata; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.LinkedList; import java.util.List; import org.apache.log4j.lf5.util.StreamUtils; import er.extensions.foundation.ERXProperties; /** * * @property er.attachment.ImageProcessor.imageMagickBinFolder */ public class ImageMagickCommandlineMetadataParser implements IERMetadataParser { public static final int BUFFER_SIZE = 8192; private File _imageMagickBinary; public ImageMagickCommandlineMetadataParser(File imageMagickBinary) { _imageMagickBinary = imageMagickBinary; } public ERMetadataDirectorySet parseMetadata(File importFile) throws ERMetadataParserException { try { ERMetadataDirectorySet metadataDirectorySet = new ERMetadataDirectorySet(); byte[] exifBytes = extractMetadata(importFile, "exif"); if (exifBytes != null && exifBytes.length > 0) { metadataDirectorySet.addMetadata(new ERUnparsedMetadataDirectory(importFile, IERMetadataDirectory.EXIF, exifBytes)); } byte[] iptcBytes = extractMetadata(importFile, "iptc"); if (iptcBytes != null && iptcBytes.length > 0) { metadataDirectorySet.addMetadata(new ERUnparsedMetadataDirectory(importFile, IERMetadataDirectory.IPTC, iptcBytes)); } return metadataDirectorySet; } catch (IOException e) { throw new ERMetadataParserException("Failed to parse metadata.", e); } } private byte[] extractMetadata(File importFile, String type) throws IOException, ERMetadataParserException { List<String> imageMagickCommandList = new LinkedList<>(); imageMagickCommandList.add(_imageMagickBinary.getAbsolutePath()); imageMagickCommandList.add(importFile.getAbsolutePath()); File metadataFile = File.createTempFile("Metadata", type); imageMagickCommandList.add(metadataFile.getAbsolutePath()); String[] imageMagickCommands = imageMagickCommandList.toArray(new String[imageMagickCommandList.size()]); Process process = Runtime.getRuntime().exec(imageMagickCommands); try { int returnValue = process.waitFor(); if (returnValue == 1) { // 1 = No metadata } else if (returnValue != 0) { throw new ERMetadataParserException("ImageMagick failed with return value " + returnValue); } } catch (InterruptedException e) { e.printStackTrace(); throw new ERMetadataParserException("ImageMagick was interrupted."); } byte[] metadataBytes; if (metadataFile.exists() && metadataFile.length() > 0) { try (FileInputStream fis = new FileInputStream(metadataFile); ByteArrayOutputStream baos = new ByteArrayOutputStream()) { StreamUtils.copy(fis, baos, ImageMagickCommandlineMetadataParser.BUFFER_SIZE); metadataBytes = baos.toByteArray(); } metadataFile.delete(); } else { metadataBytes = null; } return metadataBytes; } /** * Returns an ImageMagick metadata parser. * * @return an ImageMagick image processor * @throws IOException if an ImageMagick cannot be created */ public static IERMetadataParser imageMagickMetadataParser() throws IOException { IERMetadataParser metadataParser = null; String imageMagickBinFolder = ERXProperties.stringForKey("er.attachment.ImageProcessor.imageMagickBinFolder"); if (imageMagickBinFolder != null) { File imageMagickConvertFile = new File(imageMagickBinFolder, "convert"); if (imageMagickConvertFile.exists()) { metadataParser = new ImageMagickCommandlineMetadataParser(imageMagickConvertFile); } else { throw new IllegalArgumentException("Cannot use ImageMagick because either " + imageMagickConvertFile + " does not exist."); } } else { throw new IllegalArgumentException("Cannot use ImageMagick because you have not set 'er.attachment.ImageProcessor.imageMagickBinFolder'."); } return metadataParser; } }