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 java.io.IOException; 023import java.io.Serializable; 024import java.net.URI; 025import java.util.Collections; 026import java.util.List; 027import java.util.Map; 028import java.util.Optional; 029 030import javax.servlet.http.HttpServletRequest; 031import javax.servlet.http.HttpServletResponse; 032import javax.ws.rs.GET; 033import javax.ws.rs.Path; 034import javax.ws.rs.PathParam; 035import javax.ws.rs.Produces; 036import javax.ws.rs.QueryParam; 037import javax.ws.rs.core.Context; 038import javax.ws.rs.core.MediaType; 039import javax.ws.rs.core.Response; 040 041import org.nuxeo.ecm.core.api.Blob; 042import org.nuxeo.ecm.core.api.DocumentModel; 043import org.nuxeo.ecm.core.api.NuxeoException; 044import org.nuxeo.ecm.core.api.blobholder.BlobHolder; 045import org.nuxeo.ecm.core.api.blobholder.DocumentBlobHolder; 046import org.nuxeo.ecm.core.blob.BlobManager; 047import org.nuxeo.ecm.core.io.download.DownloadService; 048import org.nuxeo.ecm.platform.preview.api.HtmlPreviewAdapter; 049import org.nuxeo.ecm.platform.preview.helper.PreviewHelper; 050import org.nuxeo.ecm.restapi.server.jaxrs.blob.BlobObject; 051import org.nuxeo.ecm.webengine.model.Resource; 052import org.nuxeo.ecm.webengine.model.WebAdapter; 053import org.nuxeo.ecm.webengine.model.exceptions.WebResourceNotFoundException; 054import org.nuxeo.ecm.webengine.model.impl.DefaultAdapter; 055import org.nuxeo.runtime.api.Framework; 056 057/** 058 * @since 8.2 059 */ 060@WebAdapter(name = PreviewAdapter.NAME, type = "previewAdapter") 061@Produces({ MediaType.APPLICATION_JSON }) 062public class PreviewAdapter extends DefaultAdapter { 063 064 public static final String NAME = "preview"; 065 066 @GET 067 public Object preview(@QueryParam("blobPostProcessing") boolean postProcessing, @Context HttpServletRequest request, 068 @Context HttpServletResponse response) { 069 070 DocumentBlobHolder bh = getBlobHolderToPreview(); 071 072 // if it's a managed blob try to use the embed uri for preview 073 BlobManager blobManager = Framework.getService(BlobManager.class); 074 try { 075 URI uri = blobManager.getURI(bh.getBlob(), BlobManager.UsageHint.EMBED, null); 076 if (uri != null) { 077 return Response.seeOther(uri).build(); 078 } 079 } catch (IOException e) { 080 throw new NuxeoException(e); 081 } 082 083 List<Blob> previewBlobs = getPreviewBlobs(bh, postProcessing); 084 if (previewBlobs == null || previewBlobs.isEmpty()) { 085 throw new WebResourceNotFoundException("Preview not available"); 086 } 087 088 try { 089 Blob blob = previewBlobs.get(0); 090 DownloadService downloadService = Framework.getService(DownloadService.class); 091 downloadService.downloadBlob(request, response, bh.getDocument(), bh.getXpath(), blob, blob.getFilename(), 092 "preview", null, true); 093 } catch (IOException e) { 094 throw new NuxeoException(e); 095 } 096 097 return Response.ok().build(); 098 } 099 100 @GET 101 @Path("{subPath}") 102 public Object subPath(@PathParam("subPath") String subPath, 103 @QueryParam("blobPostProcessing") boolean postProcessing, @Context HttpServletRequest request, 104 @Context HttpServletResponse response) { 105 106 DocumentBlobHolder bh = getBlobHolderToPreview(); 107 108 List<Blob> previewBlobs = getPreviewBlobs(bh, postProcessing); 109 if (previewBlobs == null || previewBlobs.isEmpty()) { 110 throw new WebResourceNotFoundException("Preview not available"); 111 } 112 113 // find blob 114 Optional<Blob> subBlob = previewBlobs.stream().filter(b -> subPath.equals(b.getFilename())).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 new NuxeoException(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 Resource target = getTarget(); 153 if (isBlobTarget()) { 154 return ((BlobObject) target).getBlobHolder(); 155 } else { 156 DocumentModel doc = target.getAdapter(DocumentModel.class); 157 return (DocumentBlobHolder) doc.getAdapter(BlobHolder.class); 158 } 159 } 160 161 private boolean isBlobTarget() { 162 return getTarget().isInstanceOf("blob"); 163 } 164 165 private boolean isBlobHolder(DocumentModel doc, String xpath) { 166 DocumentBlobHolder bh = (DocumentBlobHolder) doc.getAdapter(BlobHolder.class); 167 return bh != null && bh.getXpath().equals(xpath); 168 } 169}