001/*
002 * (C) Copyright 2015-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 *     Florent Guillaume
018 *     Estelle Giuy <egiuly@nuxeo.com>
019 */
020package org.nuxeo.ecm.core.io.download;
021
022import java.io.IOException;
023import java.io.OutputStream;
024import java.io.Serializable;
025import java.util.List;
026import java.util.Map;
027import java.util.function.Consumer;
028import java.util.function.Supplier;
029
030import javax.servlet.http.HttpServletRequest;
031import javax.servlet.http.HttpServletResponse;
032
033import org.nuxeo.ecm.core.api.Blob;
034import org.nuxeo.ecm.core.api.DocumentModel;
035
036/**
037 * This service allows the download of blobs to a HTTP response.
038 *
039 * @since 7.3
040 */
041public interface DownloadService {
042
043    String EVENT_NAME = "download";
044
045    String NXFILE = "nxfile";
046
047    String NXDOWNLOADINFO = "nxdownloadinfo";
048
049    String NXBIGBLOB = "nxbigblob";
050
051    /** @deprecated since 9.1, use nxbigblob instead */
052    @Deprecated
053    String NXBIGZIPFILE = "nxbigzipfile";
054
055    /** @deprecated since 7.4, use nxfile instead */
056    @Deprecated
057    String NXBIGFILE = "nxbigfile";
058
059    String BLOBHOLDER_PREFIX = "blobholder:";
060
061    String BLOBHOLDER_0 = "blobholder:0";
062
063    public static class ByteRange {
064
065        private final long start;
066
067        private final long end;
068
069        public ByteRange(long start, long end) {
070            this.start = start;
071            this.end = end;
072        }
073
074        public long getStart() {
075            return start;
076        }
077
078        public long getEnd() {
079            return end;
080        }
081
082        public long getLength() {
083            return end - start + 1;
084        }
085    }
086
087    /**
088     * Stores the blobs for later download.
089     *
090     * @param the list of blobs to store
091     * @return the store key used for retrieving the blobs (@see {@link DownloadService#getDownloadUrl(String)}
092     * @since 9.1
093     */
094    String storeBlobs(List<Blob> blobs);
095
096    /**
097     * Gets the URL to use to download the blob at the given xpath in the given document.
098     * <p>
099     * The URL is relative to the Nuxeo Web Application context.
100     * <p>
101     * Returns something like {@code nxbigfile/reponame/docuuid/blobholder:0/foo.jpg}
102     *
103     * @param doc the document
104     * @param xpath the blob's xpath or blobholder index, or {@code null} for default
105     * @param filename the blob's filename, or {@code null} for default
106     * @return the download URL
107     */
108    String getDownloadUrl(DocumentModel doc, String xpath, String filename);
109
110    /**
111     * Gets the URL to use to download the blob at the given xpath in the given document.
112     * <p>
113     * The URL is relative to the Nuxeo Web Application context.
114     * <p>
115     * Returns something like {@code nxbigfile/reponame/docuuid/blobholder:0/foo.jpg}
116     *
117     * @param repositoryName the document repository
118     * @param docId the document id
119     * @param xpath the blob's xpath or blobholder index, or {@code null} for default
120     * @param filename the blob's filename, or {@code null} for default
121     * @return the download URL
122     */
123    String getDownloadUrl(String repositoryName, String docId, String xpath, String filename);
124
125    /**
126     * Gets the URL to use to download the blobs identified by a storage key.
127     * <p>
128     * The URL is relative to the Nuxeo Web Application context.
129     * <p>
130     * Returns something like {@code nxbigblob/key}
131     *
132     * @param key The key of stored blobs to download
133     * @return the download URL
134     * @since 9.1
135     */
136    String getDownloadUrl(String storeKey);
137
138    /**
139     * Finds a document's blob given the URL to use to download the blob.
140     *
141     * @param url the URL to use to download the blob
142     * @return the blob, or {@code null} if not found
143     * @since 9.1
144     */
145    Blob resolveBlobFromDownloadUrl(String url);
146
147    /**
148     * Handles the download of a document.
149     *
150     * @param req the request
151     * @param resp the response
152     * @param baseUrl the request baseUrl
153     * @param path the request path, without the context
154     * @since 9.1
155     */
156    void handleDownload(HttpServletRequest req, HttpServletResponse resp, String baseUrl, String path)
157            throws IOException;
158
159    /**
160     * Triggers a blobs download. Once the temporary blobs are transfered from the store, they are
161     * automatically deleted.
162     *
163     * @param storeKey the stored blobs key
164     * @param reason the download reason
165     * @since 9.1
166     */
167    void downloadBlob(HttpServletRequest request, HttpServletResponse response, String storeKey, String reason) throws IOException;
168
169    /**
170     * Triggers a blob download.
171     *
172     * @param doc the document, if available
173     * @param xpath the blob's xpath or blobholder index, if available
174     * @param blob the blob, if already fetched
175     * @param filename the filename to use
176     * @param reason the download reason
177     */
178    void downloadBlob(HttpServletRequest request, HttpServletResponse response, DocumentModel doc, String xpath,
179            Blob blob, String filename, String reason) throws IOException;
180
181    /**
182     * Triggers a blob download.
183     *
184     * @param doc the document, if available
185     * @param xpath the blob's xpath or blobholder index, if available
186     * @param blob the blob, if already fetched
187     * @param filename the filename to use
188     * @param reason the download reason
189     * @param extendedInfos an optional map of extended informations to log
190     */
191    void downloadBlob(HttpServletRequest request, HttpServletResponse response, DocumentModel doc, String xpath,
192            Blob blob, String filename, String reason, Map<String, Serializable> extendedInfos) throws IOException;
193
194    /**
195     * Triggers a blob download.
196     *
197     * @param doc the document, if available
198     * @param xpath the blob's xpath or blobholder index, if available
199     * @param blob the blob, if already fetched
200     * @param filename the filename to use
201     * @param reason the download reason
202     * @param extendedInfos an optional map of extended informations to log
203     * @param inline if not null, force the inline flag for content-disposition
204     */
205    void downloadBlob(HttpServletRequest request, HttpServletResponse response, DocumentModel doc, String xpath,
206            Blob blob, String filename, String reason, Map<String, Serializable> extendedInfos, Boolean inline)
207            throws IOException;
208
209    /**
210     * Triggers a blob download. The actual byte transfer is done through a {@link DownloadExecutor}.
211     *
212     * @param doc the document, if available
213     * @param xpath the blob's xpath or blobholder index, if available
214     * @param blob the blob, if already fetched
215     * @param filename the filename to use
216     * @param reason the download reason
217     * @param extendedInfos an optional map of extended informations to log
218     * @param inline if not null, force the inline flag for content-disposition
219     * @param blobTransferer the transferer of the actual blob
220     * @since 7.10
221     */
222    void downloadBlob(HttpServletRequest request, HttpServletResponse response, DocumentModel doc, String xpath,
223            Blob blob, String filename, String reason, Map<String, Serializable> extendedInfos, Boolean inline,
224            Consumer<ByteRange> blobTransferer) throws IOException;
225
226    /**
227     * Copies the blob stream at the given byte range into the supplied {@link OutputStream}.
228     *
229     * @param blob the blob
230     * @param byteRange the byte range
231     * @param outputStreamSupplier the {@link OutputStream} supplier
232     * @since 7.10
233     */
234    void transferBlobWithByteRange(Blob blob, ByteRange byteRange, Supplier<OutputStream> outputStreamSupplier);
235
236    /**
237     * Logs a download.
238     *
239     * @param doc the doc for which this download occurs, if available
240     * @param blobXPath the blob's xpath or blobholder index, if available
241     * @param filename the filename
242     * @param reason the download reason
243     * @param extendedInfos an optional map of extended informations to log
244     */
245    void logDownload(DocumentModel doc, String blobXPath, String filename, String reason,
246            Map<String, Serializable> extendedInfos);
247
248    /**
249     * Finds a document's blob given an xpath or blobholder index
250     *
251     * @param doc the document
252     * @param xpath the xpath or blobholder index
253     * @return the blob, or {@code null} if not found
254     */
255    Blob resolveBlob(DocumentModel doc, String xpath);
256
257    /**
258     * Checks whether the download of the blob is allowed.
259     *
260     * @param doc the doc for which this download occurs, if available
261     * @param blobXPath the blob's xpath or blobholder index, if available
262     * @param blob the blob
263     * @param reason the download reason
264     * @param extendedInfos an optional map of extended informations to log
265     * @return {@code true} if download is allowed
266     * @since 7.10
267     */
268    boolean checkPermission(DocumentModel doc, String xpath, Blob blob, String reason,
269            Map<String, Serializable> extendedInfos);
270
271}