001/* 002 * (C) Copyright 2006-20014 Nuxeo SA (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-2.1.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 */ 015package org.nuxeo.ecm.platform.preview.adapter.base; 016 017import java.io.File; 018import java.util.ArrayList; 019import java.util.List; 020 021import org.apache.commons.logging.Log; 022import org.apache.commons.logging.LogFactory; 023 024import org.nuxeo.ecm.core.api.Blob; 025import org.nuxeo.ecm.core.api.blobholder.BlobHolder; 026import org.nuxeo.ecm.core.api.blobholder.DocumentBlobHolder; 027import org.nuxeo.ecm.core.convert.api.ConversionException; 028import org.nuxeo.ecm.core.convert.api.ConversionService; 029import org.nuxeo.ecm.platform.mimetype.MimetypeDetectionException; 030import org.nuxeo.ecm.platform.mimetype.MimetypeNotFoundException; 031import org.nuxeo.ecm.platform.mimetype.interfaces.MimetypeRegistry; 032import org.nuxeo.ecm.platform.preview.adapter.MimeTypePreviewer; 033import org.nuxeo.ecm.platform.preview.adapter.PreviewAdapterManager; 034import org.nuxeo.ecm.platform.preview.api.NothingToPreviewException; 035import org.nuxeo.ecm.platform.preview.api.PreviewException; 036import org.nuxeo.runtime.api.Framework; 037 038/** 039 * Base class for preview based on "on the fly" HTML transformers 040 * 041 * @author tiry 042 */ 043public class ConverterBasedHtmlPreviewAdapter extends AbstractHtmlPreviewAdapter { 044 045 private static final Log log = LogFactory.getLog(ConverterBasedHtmlPreviewAdapter.class); 046 047 protected String defaultFieldXPath; 048 049 protected MimetypeRegistry mimeTypeService; 050 051 public ConversionService getConversionService() { 052 return Framework.getService(ConversionService.class); 053 } 054 055 @Override 056 protected PreviewAdapterManager getPreviewManager() { 057 return Framework.getService(PreviewAdapterManager.class); 058 } 059 060 protected static String getMimeType(Blob blob) { 061 if (blob == null) { 062 return null; 063 } 064 065 String srcMT = blob.getMimeType(); 066 if (srcMT == null || srcMT.startsWith("application/octet-stream")) { 067 // call MT Service 068 try { 069 MimetypeRegistry mtr = Framework.getService(MimetypeRegistry.class); 070 srcMT = mtr.getMimetypeFromFilenameAndBlobWithDefault(blob.getFilename(), blob, 071 "application/octet-stream"); 072 log.debug("mime type service returned " + srcMT); 073 } catch (MimetypeDetectionException e) { 074 log.warn("error while calling Mimetype service", e); 075 } 076 } 077 return srcMT; 078 } 079 080 protected String getDefaultPreviewFieldXPath() { 081 return defaultFieldXPath; 082 } 083 084 public void setDefaultPreviewFieldXPath(String xPath) { 085 defaultFieldXPath = xPath; 086 } 087 088 @Override 089 public List<Blob> getPreviewBlobs() throws PreviewException { 090 return getPreviewBlobs(getDefaultPreviewFieldXPath()); 091 } 092 093 @Override 094 public List<Blob> getPreviewBlobs(String xpath) throws PreviewException { 095 096 BlobHolder blobHolder2preview = getBlobHolder2preview(xpath); 097 Blob blob2Preview = getBlob2preview(blobHolder2preview); 098 099 List<Blob> blobResults = new ArrayList<>(); 100 101 String srcMT = getMimeType(blob2Preview); 102 log.debug("Source type for HTML preview =" + srcMT); 103 MimeTypePreviewer mtPreviewer = getPreviewManager().getPreviewer(srcMT); 104 if (mtPreviewer != null) { 105 blobResults = mtPreviewer.getPreview(blob2Preview, adaptedDoc); 106 return blobResults; 107 } 108 109 String converterName = getConversionService().getConverterName(srcMT, "text/html"); 110 if (converterName == null) { 111 log.debug("No dedicated converter found, using generic"); 112 converterName = "any2html"; 113 } 114 115 BlobHolder result; 116 try { 117 result = getConversionService().convert(converterName, blobHolder2preview, null); 118 setMimeType(result); 119 return result.getBlobs(); 120 } catch (ConversionException e) { 121 throw new PreviewException(e.getMessage(), e); 122 } 123 124 } 125 126 /** 127 * @param blobHolder2preview 128 * @return 129 * @throws PreviewException 130 * @since 5.7.3 131 */ 132 private Blob getBlob2preview(BlobHolder blobHolder2preview) throws PreviewException { 133 Blob blob2Preview = blobHolder2preview.getBlob(); 134 if (blob2Preview == null) { 135 throw new NothingToPreviewException("Can not preview a document without blob"); 136 } else { 137 return blob2Preview; 138 } 139 } 140 141 /** 142 * Returns a blob holder suitable for a preview. 143 * 144 * @param xpath 145 * @param adaptedDoc 146 * @return 147 * @since 5.7.3 148 */ 149 private BlobHolder getBlobHolder2preview(String xpath) { 150 if ((xpath == null) || ("default".equals(xpath))) { 151 return adaptedDoc.getAdapter(BlobHolder.class); 152 } else { 153 return new DocumentBlobHolder(adaptedDoc, xpath); 154 } 155 } 156 157 protected void setMimeType(BlobHolder result) { 158 for (Blob blob : result.getBlobs()) { 159 if ((blob.getMimeType() == null || blob.getMimeType().startsWith("application/octet-stream")) 160 && blob.getFilename().endsWith("html")) { 161 String mimeTpye = getMimeType(blob); 162 blob.setMimeType(mimeTpye); 163 } 164 } 165 } 166 167 public String getMimeType(File file) throws ConversionException { 168 try { 169 return getMimeTypeService().getMimetypeFromFile(file); 170 } catch (ConversionException e) { 171 throw new ConversionException("Could not get MimeTypeRegistry"); 172 } catch (MimetypeNotFoundException e) { 173 return "application/octet-stream"; 174 } catch (MimetypeDetectionException e) { 175 return "application/octet-stream"; 176 } 177 } 178 179 public MimetypeRegistry getMimeTypeService() throws ConversionException { 180 if (mimeTypeService == null) { 181 mimeTypeService = Framework.getService(MimetypeRegistry.class); 182 } 183 return mimeTypeService; 184 } 185 186 @Override 187 public void cleanup() { 188 189 } 190 191 @Override 192 public boolean cachable() { 193 return true; 194 } 195 196 @Override 197 public boolean hasBlobToPreview() throws PreviewException { 198 String xpath = getDefaultPreviewFieldXPath(); 199 Blob blob2Preview; 200 try { 201 blob2Preview = getBlob2preview(getBlobHolder2preview(xpath)); 202 } catch (NothingToPreviewException e) { 203 return false; 204 } 205 if (blob2Preview == null) { 206 return false; 207 } 208 return true; 209 } 210 211}