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