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