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