001/*
002 * (C) Copyright 2015 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 */
019package org.nuxeo.ecm.core.io.download;
020
021import java.io.IOException;
022import java.io.OutputStream;
023import java.io.Serializable;
024import java.util.Map;
025import java.util.function.Consumer;
026import java.util.function.Supplier;
027
028import javax.servlet.http.HttpServletRequest;
029import javax.servlet.http.HttpServletResponse;
030
031import org.nuxeo.ecm.core.api.Blob;
032import org.nuxeo.ecm.core.api.DocumentModel;
033
034/**
035 * This service allows the download of blobs to a HTTP response.
036 *
037 * @since 7.3
038 */
039public interface DownloadService {
040
041    String EVENT_NAME = "download";
042
043    String NXFILE = "nxfile";
044
045    String NXDOWNLOADINFO = "nxdownloadinfo";
046
047    String NXBIGBLOB = "nxbigblob";
048
049    String NXBIGZIPFILE = "nxbigzipfile";
050
051    String BLOBHOLDER_PREFIX = "blobholder:";
052
053    String BLOBHOLDER_0 = "blobholder:0";
054
055    public static class ByteRange {
056
057        private final long start;
058
059        private final long end;
060
061        public ByteRange(long start, long end) {
062            this.start = start;
063            this.end = end;
064        }
065
066        public long getStart() {
067            return start;
068        }
069
070        public long getEnd() {
071            return end;
072        }
073
074        public long getLength() {
075            return end - start + 1;
076        }
077    }
078
079    /**
080     * Gets the URL to use to download the blob at the given xpath in the given document.
081     * <p>
082     * The URL is relative to the Nuxeo Web Application context.
083     * <p>
084     * Returns something like {@code nxbigfile/reponame/docuuid/blobholder:0/foo.jpg}
085     *
086     * @param doc the document
087     * @param xpath the blob's xpath or blobholder index, or {@code null} for default
088     * @param filename the blob's filename, or {@code null} for default
089     * @return the download URL
090     */
091    String getDownloadUrl(DocumentModel doc, String xpath, String filename);
092
093    /**
094     * Gets the URL to use to download the blob at the given xpath in the given document.
095     * <p>
096     * The URL is relative to the Nuxeo Web Application context.
097     * <p>
098     * Returns something like {@code nxbigfile/reponame/docuuid/blobholder:0/foo.jpg}
099     *
100     * @param repositoryName the document repository
101     * @param docId the document id
102     * @param xpath the blob's xpath or blobholder index, or {@code null} for default
103     * @param filename the blob's filename, or {@code null} for default
104     * @return the download URL
105     */
106    String getDownloadUrl(String repositoryName, String docId, String xpath, String filename);
107
108    /**
109     * Triggers a blob download.
110     *
111     * @param doc the document, if available
112     * @param xpath the blob's xpath or blobholder index, if available
113     * @param blob the blob, if already fetched
114     * @param filename the filename to use
115     * @param reason the download reason
116     */
117    void downloadBlob(HttpServletRequest request, HttpServletResponse response, DocumentModel doc, String xpath,
118            Blob blob, String filename, String reason) throws IOException;
119
120    /**
121     * Triggers a blob download.
122     *
123     * @param doc the document, if available
124     * @param xpath the blob's xpath or blobholder index, if available
125     * @param blob the blob, if already fetched
126     * @param filename the filename to use
127     * @param reason the download reason
128     * @param extendedInfos an optional map of extended informations to log
129     */
130    void downloadBlob(HttpServletRequest request, HttpServletResponse response, DocumentModel doc, String xpath,
131            Blob blob, String filename, String reason, Map<String, Serializable> extendedInfos) throws IOException;
132
133    /**
134     * Triggers a blob download.
135     *
136     * @param doc the document, if available
137     * @param xpath the blob's xpath or blobholder index, if available
138     * @param blob the blob, if already fetched
139     * @param filename the filename to use
140     * @param reason the download reason
141     * @param extendedInfos an optional map of extended informations to log
142     * @param inline if not null, force the inline flag for content-disposition
143     */
144    void downloadBlob(HttpServletRequest request, HttpServletResponse response, DocumentModel doc, String xpath,
145            Blob blob, String filename, String reason, Map<String, Serializable> extendedInfos, Boolean inline)
146            throws IOException;
147
148    /**
149     * Triggers a blob download. The actual byte transfer is done through a {@link DownloadExecutor}.
150     *
151     * @param doc the document, if available
152     * @param xpath the blob's xpath or blobholder index, if available
153     * @param blob the blob, if already fetched
154     * @param filename the filename to use
155     * @param reason the download reason
156     * @param extendedInfos an optional map of extended informations to log
157     * @param inline if not null, force the inline flag for content-disposition
158     * @param blobTransferer the transferer of the actual blob
159     * @since 7.10
160     */
161    void downloadBlob(HttpServletRequest request, HttpServletResponse response, DocumentModel doc, String xpath,
162            Blob blob, String filename, String reason, Map<String, Serializable> extendedInfos, Boolean inline,
163            Consumer<ByteRange> blobTransferer) throws IOException;
164
165    /**
166     * Copies the blob stream at the given byte range into the supplied {@link OutputStream}.
167     *
168     * @param blob the blob
169     * @param byteRange the byte range
170     * @param outputStreamSupplier the {@link OutputStream} supplier
171     * @since 7.10
172     */
173    void transferBlobWithByteRange(Blob blob, ByteRange byteRange, Supplier<OutputStream> outputStreamSupplier);
174
175    /**
176     * Logs a download.
177     *
178     * @param doc the doc for which this download occurs, if available
179     * @param blobXPath the blob's xpath or blobholder index, if available
180     * @param filename the filename
181     * @param reason the download reason
182     * @param extendedInfos an optional map of extended informations to log
183     */
184    void logDownload(DocumentModel doc, String blobXPath, String filename, String reason,
185            Map<String, Serializable> extendedInfos);
186
187    /**
188     * Finds a document's blob given an xpath or blobholder index
189     *
190     * @param doc the document
191     * @param xpath the xpath or blobholder index
192     * @return the blob, or {@code null} if not found
193     */
194    Blob resolveBlob(DocumentModel doc, String xpath);
195
196    /**
197     * Checks whether the download of the blob is allowed.
198     *
199     * @param doc the doc for which this download occurs, if available
200     * @param blobXPath the blob's xpath or blobholder index, if available
201     * @param blob the blob
202     * @param reason the download reason
203     * @param extendedInfos an optional map of extended informations to log
204     * @return {@code true} if download is allowed
205     * @since 7.10
206     */
207    boolean checkPermission(DocumentModel doc, String xpath, Blob blob, String reason,
208            Map<String, Serializable> extendedInfos);
209
210}