001/* 002 * (C) Copyright 2006-2012 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Nuxeo - initial API and implementation 018 * 019 */ 020 021package org.nuxeo.template.odt; 022 023import java.io.ByteArrayInputStream; 024import java.io.File; 025import java.io.FileInputStream; 026import java.io.FileOutputStream; 027import java.io.IOException; 028import java.io.InputStream; 029import java.util.List; 030import java.util.zip.CRC32; 031import java.util.zip.ZipEntry; 032import java.util.zip.ZipOutputStream; 033 034import org.nuxeo.common.utils.FileUtils; 035import org.nuxeo.common.utils.ZipUtils; 036import org.nuxeo.ecm.core.api.Blob; 037 038/** 039 * Helper used to modify a ODT/Zip archive for addition Pictures (and potentially fragments) 040 * 041 * @author Tiry (tdelprat@nuxeo.com) 042 */ 043public class OOoArchiveModifier { 044 045 public File updateArchive(File workingDir, File oooFile, List<Blob> blobs) throws IOException { 046 if (blobs == null || blobs.size() == 0) { 047 return oooFile; 048 } 049 050 File unzipDir = new File(workingDir, "unzip-" + oooFile.getName()); 051 unzipDir.mkdirs(); 052 053 ZipUtils.unzip(oooFile, unzipDir); 054 055 File pictureDirs = new File(unzipDir, "Pictures"); 056 if (!pictureDirs.exists()) { 057 pictureDirs.mkdir(); 058 pictureDirs = new File(unzipDir, "Pictures"); 059 } 060 061 File contentDirs = new File(unzipDir, "Content"); 062 if (!contentDirs.exists()) { 063 contentDirs.mkdir(); 064 contentDirs = new File(unzipDir, "Content"); 065 } 066 067 StringBuffer blobsManifest = new StringBuffer(); 068 for (Blob blob : blobs) { 069 if (blob.getMimeType().startsWith("image")) { 070 FileUtils.copyToFile(blob.getStream(), new File(pictureDirs, blob.getFilename())); 071 } else { 072 FileUtils.copyToFile(blob.getStream(), new File(contentDirs, blob.getFilename())); 073 } 074 075 blobsManifest.append("<manifest:file-entry manifest:media-type=\""); 076 blobsManifest.append(blob.getMimeType()); 077 if (blob.getMimeType().startsWith("image")) { 078 blobsManifest.append("\" manifest:full-path=\"Pictures/"); 079 } else { 080 blobsManifest.append("\" manifest:full-path=\"Content/"); 081 } 082 blobsManifest.append(blob.getFilename()); 083 blobsManifest.append("\"/>\n"); 084 } 085 086 File xmlManifestFile = new File(unzipDir.getPath() + "/META-INF/manifest.xml"); 087 String xmlManifest = FileUtils.readFile(xmlManifestFile); 088 int idx = xmlManifest.indexOf("</manifest:manifest>"); 089 xmlManifest = xmlManifest.substring(0, idx) + blobsManifest.toString() + xmlManifest.substring(idx); 090 FileUtils.writeFile(xmlManifestFile, xmlManifest.getBytes()); 091 092 String path = oooFile.getAbsolutePath(); 093 094 oooFile.delete(); 095 096 oooFile = new File(path); 097 oooFile.createNewFile(); 098 099 // ZipUtils.zip(unzipDir.listFiles(), oooFile); 100 mkOOoZip(unzipDir, oooFile); 101 102 FileUtils.deleteTree(unzipDir); 103 104 return oooFile; 105 106 } 107 108 protected void mkOOoZip(File directory, File outFile) throws IOException { 109 110 ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(outFile)); 111 112 File manif = new File(directory, "mimetype"); 113 writeOOoEntry(zipOutputStream, manif.getName(), manif, ZipEntry.STORED); 114 115 for (File fileEntry : directory.listFiles()) { 116 if (!fileEntry.getName().equals(manif.getName())) { 117 writeOOoEntry(zipOutputStream, fileEntry.getName(), fileEntry, ZipEntry.DEFLATED); 118 } 119 } 120 121 zipOutputStream.close(); 122 } 123 124 protected void writeOOoEntry(ZipOutputStream zipOutputStream, String entryName, File fileEntry, int zipMethod) throws IOException { 125 126 if (fileEntry.isDirectory()) { 127 entryName = entryName + "/"; 128 ZipEntry zentry = new ZipEntry(entryName); 129 zipOutputStream.putNextEntry(zentry); 130 zipOutputStream.closeEntry(); 131 for (File child : fileEntry.listFiles()) { 132 writeOOoEntry(zipOutputStream, entryName + child.getName(), child, zipMethod); 133 } 134 return; 135 } 136 137 ZipEntry zipEntry = new ZipEntry(entryName); 138 InputStream entryInputStream = new FileInputStream(fileEntry); 139 zipEntry.setMethod(zipMethod); 140 if (zipMethod == ZipEntry.STORED) { 141 byte[] inputBytes = FileUtils.readBytes(entryInputStream); 142 CRC32 crc = new CRC32(); 143 crc.update(inputBytes); 144 zipEntry.setCrc(crc.getValue()); 145 zipEntry.setSize(inputBytes.length); 146 zipEntry.setCompressedSize(inputBytes.length); 147 zipOutputStream.putNextEntry(zipEntry); 148 FileUtils.copy(new ByteArrayInputStream(inputBytes), zipOutputStream); 149 } else { 150 zipOutputStream.putNextEntry(zipEntry); 151 FileUtils.copy(entryInputStream, zipOutputStream); 152 } 153 try { 154 entryInputStream.close(); 155 } catch (IOException e) { 156 // NOP 157 } 158 zipOutputStream.closeEntry(); 159 } 160 161}