001/* 002 * (C) Copyright 2015-2017 Nuxeo (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 * Nelson Silva 019 * Gabriel Barata 020 */ 021package org.nuxeo.ecm.core.blob; 022 023import java.io.File; 024import java.io.IOException; 025import java.io.InputStream; 026import java.net.URI; 027import java.util.Collections; 028import java.util.List; 029import java.util.Map; 030 031import javax.servlet.http.HttpServletRequest; 032 033import org.nuxeo.ecm.core.api.Blob; 034import org.nuxeo.ecm.core.api.NuxeoException; 035import org.nuxeo.ecm.core.blob.BlobManager.UsageHint; 036import org.nuxeo.ecm.core.blob.apps.AppLink; 037import org.nuxeo.ecm.core.blob.binary.BinaryGarbageCollector; 038import org.nuxeo.ecm.core.blob.binary.BinaryManager; 039 040/** 041 * Interface for a provider of {@link Blob}s, which knows how to read and write them. 042 * 043 * @since 7.2 044 */ 045public interface BlobProvider { 046 047 /** 048 * Initializes the blob provider. 049 * 050 * @param blobProviderId the blob provider id for this binary manager 051 * @param properties initialization properties 052 * 053 * @since 7.3 054 */ 055 void initialize(String blobProviderId, Map<String, String> properties) throws IOException; 056 057 /** 058 * Closes this blob provider and releases resources that may be held by it. 059 * 060 * @since 7.3 061 */ 062 void close(); 063 064 /** 065 * Checks whether this blob provider uses "record mode". 066 * <p> 067 * Record mode has the following characteristics: 068 * <ul> 069 * <li>transactional (blobs aren't actually written/deleted until the transaction commits, and transaction rollback 070 * is possible), 071 * <li>can replace or delete a document's blob. 072 * </ul> 073 * 074 * @since 11.1 075 */ 076 default boolean isRecordMode() { 077 return false; 078 } 079 080 /** 081 * Checks whether this blob provider is transactional. 082 * <p> 083 * A transactional blob provider only writes blobs to final storage at commit time. 084 * 085 * @since 11.1 086 */ 087 default boolean isTransactional() { 088 return false; 089 } 090 091 /** 092 * Checks whether this blob provider is transient: blobs may disappear after a while, so a caller should not rely on 093 * them being available forever. 094 * 095 * @since 10.1 096 */ 097 default boolean isTransient() { 098 return false; 099 } 100 101 /** 102 * Checks whether this blob provider allows byte ranges in keys. 103 * 104 * @since 11.1 105 */ 106 default boolean allowByteRange() { 107 return false; 108 } 109 110 /** 111 * Reads a {@link Blob} from storage. 112 * 113 * @param blobInfoContext the blob information context 114 * @return the blob 115 * @since 11.1 116 */ 117 default Blob readBlob(BlobInfoContext blobInfoContext) throws IOException { 118 return readBlob(blobInfoContext.blobInfo); 119 } 120 121 /** 122 * Reads a {@link Blob} from storage. 123 * 124 * @param blobInfo the blob information 125 * @return the blob 126 */ 127 Blob readBlob(BlobInfo blobInfo) throws IOException; 128 129 /** 130 * Writes a {@link Blob} to storage and returns information about it. 131 * <p> 132 * Called to store a user-created blob. 133 * 134 * @param blobContext the blob context 135 * @return the blob key 136 * @since 11.1 137 */ 138 default String writeBlob(BlobContext blobContext) throws IOException { 139 return writeBlob(blobContext.blob); 140 } 141 142 /** 143 * Writes a {@link Blob} to storage and returns information about it. 144 * <p> 145 * Called to store a user-created blob. 146 * 147 * @param blob the blob 148 * @return the blob key 149 * @since 9.2 150 */ 151 String writeBlob(Blob blob) throws IOException; 152 153 /** 154 * Updates a blob's properties in storage. 155 * 156 * @param blobUpdateContext the blob update context 157 * @since 11.1 158 */ 159 default void updateBlob(BlobUpdateContext blobUpdateContext) throws IOException { 160 // ignore properties updates by default 161 } 162 163 /** 164 * Deletes a blob from storage. Only meaningful for a record blob provider. 165 * 166 * @param blobContext the blob context 167 * @see #isRecordMode 168 * @since 11.1 169 */ 170 default void deleteBlob(BlobContext blobContext) { 171 throw new UnsupportedOperationException(); 172 } 173 174 /** 175 * Gets the status of a blob. 176 * 177 * @param blob the blob 178 * @since 11.1 179 */ 180 default BlobStatus getStatus(ManagedBlob blob) throws IOException { 181 return new BlobStatus(); 182 } 183 184 /** 185 * Checks if user update is supported. 186 * <p> 187 * A user update refers to the fact that a blob from this provider may be overwritten with another blob, wherever 188 * the original blob may occur (usually in a document property). 189 * 190 * @return {@code true} if user update is supported 191 * @since 7.10 192 */ 193 boolean supportsUserUpdate(); 194 195 /** 196 * Checks if sync is supported. 197 * <p> 198 * Sync refers to the fact that a blob from this provider may be synced with a remote system (like Nuxeo Drive) or 199 * with a process that updates things in the blob (like Binary Metadata, or WOPI). 200 * 201 * @return {@code true} if sync is supported 202 * @since 11.1 203 */ 204 default boolean supportsSync() { 205 return supportsUserUpdate() && getBinaryManager() != null; 206 } 207 208 /** 209 * Gets an {@link InputStream} for a byte range of a managed blob. 210 * 211 * @param blobKey the blob key 212 * @param byteRange the byte range 213 * @return the stream 214 * @since 11.1 215 */ 216 default InputStream getStream(String blobKey, ByteRange byteRange) throws IOException { 217 throw new UnsupportedOperationException(); 218 } 219 220 /** 221 * Gets an {@link InputStream} for the data of a managed blob. 222 * <p> 223 * Like all {@link InputStream}, the result must be closed when done with it to avoid resource leaks. 224 * 225 * @param blob the managed blob 226 * @return the stream 227 * @since 7.3 228 */ 229 default InputStream getStream(ManagedBlob blob) throws IOException { 230 return null; 231 } 232 233 /** 234 * Gets a {@link File} (if one exists) for the data of a managed blob. 235 * 236 * @param blob the managed blob 237 * @return the file, or {@code null} if no underlying file is available 238 * @since 11.1 239 */ 240 default File getFile(ManagedBlob blob) { 241 return null; 242 } 243 244 /** 245 * Gets an {@link InputStream} for a thumbnail of a managed blob. 246 * <p> 247 * Like all {@link InputStream}, the result must be closed when done with it to avoid resource leaks. 248 * 249 * @param blob the managed blob 250 * @return the stream 251 * @since 7.3 252 */ 253 default InputStream getThumbnail(ManagedBlob blob) throws IOException { 254 return null; 255 } 256 257 /** 258 * Gets an {@link URI} for the content of a managed blob. 259 * 260 * @param blob the managed blob 261 * @param hint {@link UsageHint} 262 * @param servletRequest the servlet request, or {@code null} 263 * @return the {@link URI}, or {@code null} if none available 264 * @since 7.4 265 */ 266 default URI getURI(ManagedBlob blob, UsageHint hint, HttpServletRequest servletRequest) throws IOException { 267 return null; 268 } 269 270 /** 271 * Gets a map of available MIME type conversions and corresponding {@link URI} for a managed blob. 272 * 273 * @param blob the managed blob 274 * @param hint {@link UsageHint} 275 * @return a map of MIME types and {@link URI}, which may be empty 276 * @since 7.3 277 */ 278 default Map<String, URI> getAvailableConversions(ManagedBlob blob, UsageHint hint) throws IOException { 279 return Collections.emptyMap(); 280 } 281 282 /** 283 * Checks if the conversion to the given {@code mimeType} is supported by the {@code blob}. 284 * 285 * @param blob the managed blob 286 * @param mimeType the destination mime type 287 * @return {@code true} if this managed blob supports the conversion to the given mime type 288 * @since 10.1 289 */ 290 default boolean canConvert(ManagedBlob blob, String mimeType) { 291 try { 292 Map<String, URI> availableConversions = getAvailableConversions(blob, UsageHint.STREAM); 293 return availableConversions.containsKey(mimeType); 294 } catch (IOException e) { 295 throw new NuxeoException(e); 296 } 297 } 298 299 /** 300 * Returns true if version of the blob is a version. 301 * <p> 302 * 303 * @param blob the managed blob 304 * @return true if the blob is a version or a revision 305 * @since 7.3 306 */ 307 default boolean isVersion(ManagedBlob blob) { 308 return false; 309 } 310 311 /** 312 * Returns a list of application links for the given blob. 313 * 314 * @since 7.3 315 */ 316 default List<AppLink> getAppLinks(String user, ManagedBlob blob) throws IOException { 317 return Collections.emptyList(); 318 } 319 320 /** 321 * Gets the associated binary manager, if any. 322 * 323 * @return the binary manager, or {@code null} 324 * @since 7.4 325 */ 326 default BinaryManager getBinaryManager() { 327 return null; 328 } 329 330 /** 331 * Gets the associated garbage collector, if any. 332 * 333 * @return the garbage collector, or {@code null} 334 * @since 11.1 335 */ 336 default BinaryGarbageCollector getBinaryGarbageCollector() { 337 BinaryManager binaryManager = getBinaryManager(); 338 return binaryManager == null ? null : binaryManager.getGarbageCollector(); 339 } 340 341 /** 342 * Checks if the blob provider performs external access control checks. 343 * 344 * @param blobInfo the blob information to be read 345 * @return {@code true} if the provider performs security checks before reading a blob, {@code false} otherwise 346 * @since 8.4 347 */ 348 default boolean performsExternalAccessControl(BlobInfo blobInfo) { 349 return false; 350 } 351 352 /** 353 * Returns the properties of the blob provider. 354 * 355 * @since 10.2 356 */ 357 Map<String, String> getProperties(); 358 359 /** 360 * Checks if current user has the rights to create blobs in the blob provider using a key. 361 * 362 * @since 10.2 363 */ 364 default boolean hasCreateFromKeyPermission() { 365 return false; 366 } 367 368}