001/* 002 * (C) Copyright 2002-2010 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 */ 018package org.nuxeo.ecm.platform.convert.plugins; 019 020import java.io.File; 021import java.io.IOException; 022import java.util.ArrayList; 023import java.util.List; 024 025import org.apache.commons.lang.StringEscapeUtils; 026import org.apache.commons.logging.Log; 027import org.apache.commons.logging.LogFactory; 028import org.nuxeo.common.utils.FileUtils; 029import org.nuxeo.common.utils.Path; 030import org.nuxeo.common.utils.ZipUtils; 031import org.nuxeo.ecm.core.api.Blob; 032import org.nuxeo.ecm.core.api.Blobs; 033import org.nuxeo.ecm.core.api.NuxeoException; 034import org.nuxeo.ecm.core.convert.api.ConversionException; 035import org.nuxeo.ecm.core.convert.cache.SimpleCachableBlobHolder; 036import org.nuxeo.ecm.platform.mimetype.MimetypeDetectionException; 037import org.nuxeo.ecm.platform.mimetype.MimetypeNotFoundException; 038import org.nuxeo.ecm.platform.mimetype.interfaces.MimetypeRegistry; 039import org.nuxeo.runtime.api.Framework; 040 041/** 042 * Cachable implementation of a zip file. 043 * 044 * @author Laurent Doguin 045 */ 046public class ZipCachableBlobHolder extends SimpleCachableBlobHolder { 047 048 private static final Log log = LogFactory.getLog(ZipCachableBlobHolder.class); 049 050 protected Blob zipBlob; 051 052 protected MimetypeRegistry mimeTypeService; 053 054 protected String key; 055 056 public ZipCachableBlobHolder() { 057 } 058 059 public ZipCachableBlobHolder(Blob zipBlob) { 060 this.zipBlob = zipBlob; 061 } 062 063 public Blob getBlob(String path) throws IOException, MimetypeNotFoundException, MimetypeDetectionException, 064 ConversionException { 065 String filePath = key + path; 066 File file = new File(filePath); 067 Blob blob = Blobs.createBlob(file); 068 String mimeType = getMimeTypeService().getMimetypeFromBlob(blob); 069 blob.setMimeType(mimeType); 070 blob.setFilename(path); 071 return blob; 072 } 073 074 @Override 075 public Blob getBlob() { 076 return zipBlob; 077 } 078 079 @Override 080 public List<Blob> getBlobs() { 081 if (blobs == null) { 082 try { 083 load(key); 084 } catch (IOException e) { 085 throw new NuxeoException(e); 086 } 087 } 088 return blobs; 089 } 090 091 @Override 092 public void load(String path) throws IOException { 093 blobs = new ArrayList<Blob>(); 094 File base = new File(path); 095 try { 096 if (base.isDirectory()) { 097 addDirectoryToList(base, ""); 098 } else { 099 File file = new File(path); 100 String mimeType = getMimeType(file); 101 Blob mainBlob = Blobs.createBlob(file, mimeType, null, file.getName()); 102 blobs.add(mainBlob); 103 } 104 105 orderIndexPageFirst(blobs); 106 } catch (ConversionException e) { 107 throw new RuntimeException("Blob loading from cache failed", e.getCause()); 108 } 109 } 110 111 @Override 112 public String persist(String basePath) throws IOException { 113 Path path = new Path(basePath); 114 path = path.append(getHash()); 115 File dir = new File(path.toString()); 116 dir.mkdir(); 117 ZipUtils.unzip(zipBlob.getStream(), dir); 118 key = dir.getAbsolutePath(); 119 120 // Check if creating an index.html file is needed 121 load(path.toString()); 122 if (blobs != null && !blobs.get(0).getFilename().contains("index.html")) { 123 log.info("Any index.html file found, generate a listing as index page."); 124 File index = new File(dir, "index.html"); 125 if (index.createNewFile()) { 126 Blob indexBlob = createIndexBlob(); 127 blobs.add(0, indexBlob); 128 FileUtils.writeFile(index, indexBlob.getByteArray()); 129 } else { 130 log.info("Unable to create index.html file"); 131 } 132 } 133 134 return key; 135 } 136 137 public String getMimeType(File file) throws ConversionException { 138 try { 139 return getMimeTypeService().getMimetypeFromFile(file); 140 } catch (ConversionException e) { 141 throw new ConversionException("Could not get MimeTypeRegistry", e); 142 } catch (MimetypeNotFoundException | MimetypeDetectionException e) { 143 return "application/octet-stream"; 144 } 145 } 146 147 public MimetypeRegistry getMimeTypeService() throws ConversionException { 148 if (mimeTypeService == null) { 149 mimeTypeService = Framework.getService(MimetypeRegistry.class); 150 } 151 return mimeTypeService; 152 } 153 154 protected Blob createIndexBlob() { 155 StringBuilder page = new StringBuilder("<html><body>"); 156 page.append("<h1>").append(StringEscapeUtils.escapeJavaScript(StringEscapeUtils.escapeHtml(zipBlob.getFilename()))).append("</h1>"); 157 page.append("<ul>"); 158 for (Blob blob : blobs) { 159 String fn = StringEscapeUtils.escapeJavaScript(StringEscapeUtils.escapeHtml(blob.getFilename())); 160 page.append("<li><a href=\"").append(fn).append("\">"); 161 page.append(fn); 162 page.append("</a></li>"); 163 } 164 page.append("</ul></body></html>"); 165 return Blobs.createBlob(page.toString()); 166 } 167}