001/* 002 * (C) Copyright 2016 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 * 018 * Nelson Silva <nsilva@nuxeo.com> 019 */ 020package org.nuxeo.ecm.restapi.server.jaxrs.adapters; 021 022import org.nuxeo.ecm.core.api.Blob; 023import org.nuxeo.ecm.core.api.DocumentModel; 024import org.nuxeo.ecm.core.api.blobholder.BlobHolder; 025import org.nuxeo.ecm.core.api.blobholder.DocumentBlobHolder; 026import org.nuxeo.ecm.core.blob.BlobManager; 027import org.nuxeo.ecm.core.io.download.DownloadService; 028import org.nuxeo.ecm.platform.preview.api.HtmlPreviewAdapter; 029import org.nuxeo.ecm.platform.preview.helper.PreviewHelper; 030import org.nuxeo.ecm.restapi.server.jaxrs.blob.BlobObject; 031import org.nuxeo.ecm.webengine.WebException; 032import org.nuxeo.ecm.webengine.model.WebAdapter; 033import org.nuxeo.ecm.webengine.model.exceptions.WebResourceNotFoundException; 034import org.nuxeo.ecm.webengine.model.impl.DefaultAdapter; 035import org.nuxeo.runtime.api.Framework; 036import javax.servlet.http.HttpServletRequest; 037import javax.servlet.http.HttpServletResponse; 038import javax.ws.rs.GET; 039import javax.ws.rs.Path; 040import javax.ws.rs.PathParam; 041import javax.ws.rs.Produces; 042import javax.ws.rs.QueryParam; 043import javax.ws.rs.core.Context; 044import javax.ws.rs.core.MediaType; 045import javax.ws.rs.core.Response; 046 047import java.io.IOException; 048import java.io.Serializable; 049import java.io.UncheckedIOException; 050import java.net.URI; 051import java.util.Collections; 052import java.util.List; 053import java.util.Map; 054import java.util.Optional; 055 056/** 057 * @since 8.2 058 */ 059@WebAdapter(name = PreviewAdapter.NAME, type = "previewAdapter") 060@Produces({ MediaType.APPLICATION_JSON }) 061public class PreviewAdapter extends DefaultAdapter { 062 063 public static final String NAME = "preview"; 064 065 @GET 066 public Object preview(@QueryParam("blobPostProcessing") boolean postProcessing, @Context HttpServletRequest request, 067 @Context HttpServletResponse response) { 068 069 DocumentBlobHolder bh = getBlobHolderToPreview(); 070 071 // if it's a managed blob try to use the embed uri for preview 072 BlobManager blobManager = Framework.getService(BlobManager.class); 073 try { 074 URI uri = blobManager.getURI(bh.getBlob(), BlobManager.UsageHint.EMBED, null); 075 if (uri != null) { 076 return Response.seeOther(uri).build(); 077 } 078 } catch (IOException e) { 079 throw WebException.wrap(e); 080 } 081 082 List<Blob> previewBlobs = getPreviewBlobs(bh, postProcessing); 083 if (previewBlobs == null || previewBlobs.isEmpty()) { 084 throw new WebResourceNotFoundException("Preview not available"); 085 } 086 087 try { 088 Blob blob = previewBlobs.get(0); 089 DownloadService downloadService = Framework.getService(DownloadService.class); 090 downloadService.downloadBlob(request, response, bh.getDocument(), bh.getXpath(), blob, blob.getFilename(), 091 "preview", null, true); 092 } catch (IOException e) { 093 throw WebException.wrap(e); 094 } 095 096 return Response.ok().build(); 097 } 098 099 @GET 100 @Path("{subPath}") 101 public Object subPath(@PathParam("subPath") String subPath, @QueryParam("blobPostProcessing") boolean postProcessing, 102 @Context HttpServletRequest request, @Context HttpServletResponse response) { 103 104 DocumentBlobHolder bh = getBlobHolderToPreview(); 105 106 List<Blob> previewBlobs = getPreviewBlobs(bh, postProcessing); 107 if (previewBlobs == null || previewBlobs.isEmpty()) { 108 throw new WebResourceNotFoundException("Preview not available"); 109 } 110 111 // find blob 112 Optional<Blob> subBlob = previewBlobs.stream() 113 .filter(b -> subPath.equals(b.getFilename())) 114 .findFirst(); 115 116 if (!subBlob.isPresent()) { 117 throw new WebResourceNotFoundException(String.format("Preview blob %s not found", subPath)); 118 } 119 120 try { 121 Blob blob = subBlob.get(); 122 DownloadService downloadService = Framework.getService(DownloadService.class); 123 Map<String, Serializable> extendedInfos = Collections.singletonMap("subPath", subPath); 124 downloadService.downloadBlob(request, response, bh.getDocument(), bh.getXpath(), blob, blob.getFilename(), 125 "preview", extendedInfos, true); 126 } catch (IOException e) { 127 throw WebException.wrap(e); 128 } 129 130 return Response.ok().build(); 131 } 132 133 private List<Blob> getPreviewBlobs(DocumentBlobHolder bh, boolean blobPostProcessing) { 134 DocumentModel doc = bh.getDocument(); 135 String xpath = bh.getXpath(); 136 HtmlPreviewAdapter preview; 137 138 if (isBlobTarget() && !isBlobHolder(doc, xpath)) { 139 preview = PreviewHelper.getBlobPreviewAdapter(doc); 140 return preview.getFilePreviewBlobs(xpath, blobPostProcessing); 141 } 142 143 preview = doc.getAdapter(HtmlPreviewAdapter.class); 144 if (preview == null) { 145 return null; 146 } 147 148 return preview.getFilePreviewBlobs(blobPostProcessing); 149 } 150 151 private DocumentBlobHolder getBlobHolderToPreview() { 152 DocumentModel doc; 153 if (isBlobTarget()) { 154 BlobObject target = (BlobObject) getTarget(); 155 doc = target.getDocument(); 156 if (!isBlobHolder(doc, target.getXpath())) { 157 return new DocumentBlobHolder(doc, target.getXpath()); 158 } 159 } else { 160 doc = getTarget().getAdapter(DocumentModel.class); 161 } 162 163 return (DocumentBlobHolder) doc.getAdapter(BlobHolder.class); 164 } 165 166 private boolean isBlobTarget() { 167 return getTarget().isInstanceOf("blob"); 168 } 169 170 private boolean isBlobHolder(DocumentModel doc, String xpath) { 171 DocumentBlobHolder bh = (DocumentBlobHolder) doc.getAdapter(BlobHolder.class); 172 return bh != null && bh.getXpath().equals(xpath); 173 } 174}