001/* 002 * (C) Copyright 2006-20012 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Nuxeo - initial API and implementation 016 * 017 */ 018 019package org.nuxeo.template.odt; 020 021import java.io.ByteArrayInputStream; 022import java.io.File; 023import java.io.FileInputStream; 024import java.io.FileOutputStream; 025import java.io.IOException; 026import java.io.InputStream; 027import java.util.List; 028import java.util.zip.CRC32; 029import java.util.zip.ZipEntry; 030import java.util.zip.ZipOutputStream; 031 032import org.nuxeo.common.utils.FileUtils; 033import org.nuxeo.common.utils.ZipUtils; 034import org.nuxeo.ecm.core.api.Blob; 035 036/** 037 * Helper used to modify a ODT/Zip archive for addition Pictures (and potentially fragments) 038 * 039 * @author Tiry (tdelprat@nuxeo.com) 040 */ 041public class OOoArchiveModifier { 042 043 public File updateArchive(File workingDir, File oooFile, List<Blob> blobs) throws IOException { 044 if (blobs == null || blobs.size() == 0) { 045 return oooFile; 046 } 047 048 File unzipDir = new File(workingDir, "unzip-" + oooFile.getName()); 049 unzipDir.mkdirs(); 050 051 ZipUtils.unzip(oooFile, unzipDir); 052 053 File pictureDirs = new File(unzipDir, "Pictures"); 054 if (!pictureDirs.exists()) { 055 pictureDirs.mkdir(); 056 pictureDirs = new File(unzipDir, "Pictures"); 057 } 058 059 File contentDirs = new File(unzipDir, "Content"); 060 if (!contentDirs.exists()) { 061 contentDirs.mkdir(); 062 contentDirs = new File(unzipDir, "Content"); 063 } 064 065 StringBuffer blobsManifest = new StringBuffer(); 066 for (Blob blob : blobs) { 067 if (blob.getMimeType().startsWith("image")) { 068 FileUtils.copyToFile(blob.getStream(), new File(pictureDirs, blob.getFilename())); 069 } else { 070 FileUtils.copyToFile(blob.getStream(), new File(contentDirs, blob.getFilename())); 071 } 072 073 blobsManifest.append("<manifest:file-entry manifest:media-type=\""); 074 blobsManifest.append(blob.getMimeType()); 075 if (blob.getMimeType().startsWith("image")) { 076 blobsManifest.append("\" manifest:full-path=\"Pictures/"); 077 } else { 078 blobsManifest.append("\" manifest:full-path=\"Content/"); 079 } 080 blobsManifest.append(blob.getFilename()); 081 blobsManifest.append("\"/>\n"); 082 } 083 084 File xmlManifestFile = new File(unzipDir.getPath() + "/META-INF/manifest.xml"); 085 String xmlManifest = FileUtils.readFile(xmlManifestFile); 086 int idx = xmlManifest.indexOf("</manifest:manifest>"); 087 xmlManifest = xmlManifest.substring(0, idx) + blobsManifest.toString() + xmlManifest.substring(idx); 088 FileUtils.writeFile(xmlManifestFile, xmlManifest.getBytes()); 089 090 String path = oooFile.getAbsolutePath(); 091 092 oooFile.delete(); 093 094 oooFile = new File(path); 095 oooFile.createNewFile(); 096 097 // ZipUtils.zip(unzipDir.listFiles(), oooFile); 098 mkOOoZip(unzipDir, oooFile); 099 100 FileUtils.deleteTree(unzipDir); 101 102 return oooFile; 103 104 } 105 106 protected void mkOOoZip(File directory, File outFile) throws IOException { 107 108 ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(outFile)); 109 110 File manif = new File(directory, "mimetype"); 111 writeOOoEntry(zipOutputStream, manif.getName(), manif, ZipEntry.STORED); 112 113 for (File fileEntry : directory.listFiles()) { 114 if (!fileEntry.getName().equals(manif.getName())) { 115 writeOOoEntry(zipOutputStream, fileEntry.getName(), fileEntry, ZipEntry.DEFLATED); 116 } 117 } 118 119 zipOutputStream.close(); 120 } 121 122 protected void writeOOoEntry(ZipOutputStream zipOutputStream, String entryName, File fileEntry, int zipMethod) throws IOException { 123 124 if (fileEntry.isDirectory()) { 125 entryName = entryName + "/"; 126 ZipEntry zentry = new ZipEntry(entryName); 127 zipOutputStream.putNextEntry(zentry); 128 zipOutputStream.closeEntry(); 129 for (File child : fileEntry.listFiles()) { 130 writeOOoEntry(zipOutputStream, entryName + child.getName(), child, zipMethod); 131 } 132 return; 133 } 134 135 ZipEntry zipEntry = new ZipEntry(entryName); 136 InputStream entryInputStream = new FileInputStream(fileEntry); 137 zipEntry.setMethod(zipMethod); 138 if (zipMethod == ZipEntry.STORED) { 139 byte[] inputBytes = FileUtils.readBytes(entryInputStream); 140 CRC32 crc = new CRC32(); 141 crc.update(inputBytes); 142 zipEntry.setCrc(crc.getValue()); 143 zipEntry.setSize(inputBytes.length); 144 zipEntry.setCompressedSize(inputBytes.length); 145 zipOutputStream.putNextEntry(zipEntry); 146 FileUtils.copy(new ByteArrayInputStream(inputBytes), zipOutputStream); 147 } else { 148 zipOutputStream.putNextEntry(zipEntry); 149 FileUtils.copy(entryInputStream, zipOutputStream); 150 } 151 try { 152 entryInputStream.close(); 153 } catch (IOException e) { 154 // NOP 155 } 156 zipOutputStream.closeEntry(); 157 } 158 159}