Author: mattryan
Date: Thu Jul 18 17:07:38 2019
New Revision: 1863326

URL: http://svn.apache.org/viewvc?rev=1863326&view=rev
Log:
OAK-7998: Return null if requesting download URI on nonexistent binary

Modified:
    
jackrabbit/oak/branches/1.10/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureBlobStoreBackend.java
    
jackrabbit/oak/branches/1.10/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3Backend.java
    
jackrabbit/oak/branches/1.10/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/AbstractDataRecordAccessProviderTest.java
    
jackrabbit/oak/branches/1.10/oak-doc/src/site/markdown/features/direct-binary-access.md

Modified: 
jackrabbit/oak/branches/1.10/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureBlobStoreBackend.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.10/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureBlobStoreBackend.java?rev=1863326&r1=1863325&r2=1863326&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.10/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureBlobStoreBackend.java
 (original)
+++ 
jackrabbit/oak/branches/1.10/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureBlobStoreBackend.java
 Thu Jul 18 17:07:38 2019
@@ -763,7 +763,27 @@ public class AzureBlobStoreBackend exten
     URI createHttpDownloadURI(@NotNull DataIdentifier identifier,
                               @NotNull DataRecordDownloadOptions 
downloadOptions) {
         URI uri = null;
+
+        // When running unit test from Maven, it doesn't always honor the 
@NotNull decorators
+        if (null == identifier) throw new NullPointerException("identifier");
+        if (null == downloadOptions) throw new 
NullPointerException("downloadOptions");
+
         if (httpDownloadURIExpirySeconds > 0) {
+
+            // Check if this identifier exists.  If not, we want to return null
+            // even if the identifier is in the download URI cache.
+
+            try {
+                if (! exists(identifier)) {
+                    LOG.warn("Cannot create download URI for nonexistent blob 
{}; returning null", getKeyName(identifier));
+                    return null;
+                }
+            }
+            catch (DataStoreException e) {
+                LOG.warn("Cannot create download URI for blob {} (caught 
DataStoreException); returning null", getKeyName(identifier), e);
+                return null;
+            }
+
             if (null != httpDownloadURICache) {
                 uri = httpDownloadURICache.getIfPresent(identifier);
             }

Modified: 
jackrabbit/oak/branches/1.10/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3Backend.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.10/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3Backend.java?rev=1863326&r1=1863325&r2=1863326&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.10/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3Backend.java
 (original)
+++ 
jackrabbit/oak/branches/1.10/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3Backend.java
 Thu Jul 18 17:07:38 2019
@@ -17,6 +17,10 @@
 
 package org.apache.jackrabbit.oak.blob.cloud.s3;
 
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.Iterables.filter;
+import static java.lang.Thread.currentThread;
+
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
@@ -92,10 +96,6 @@ import org.jetbrains.annotations.NotNull
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.Iterables.filter;
-import static java.lang.Thread.currentThread;
-
 /**
  * A data store backend that stores data on Amazon S3.
  */
@@ -740,6 +740,21 @@ public class S3Backend extends AbstractS
             return null;
         }
 
+        // When running unit test from Maven, it doesn't always honor the 
@NotNull decorators
+        if (null == identifier) throw new NullPointerException("identifier");
+        if (null == downloadOptions) throw new 
NullPointerException("downloadOptions");
+
+        try {
+            if (! exists(identifier)) {
+                LOG.warn("Cannot create download URI for nonexistent blob {}; 
returning null", getKeyName(identifier));
+                return null;
+            }
+        }
+        catch (DataStoreException e) {
+            LOG.warn("Cannot create download URI for blob {} (caught 
DataStoreException); returning null", getKeyName(identifier), e);
+            return null;
+        }
+
         URI uri = null;
         // if cache is enabled, check the cache
         if (httpDownloadURICache != null) {

Modified: 
jackrabbit/oak/branches/1.10/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/AbstractDataRecordAccessProviderTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.10/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/AbstractDataRecordAccessProviderTest.java?rev=1863326&r1=1863325&r2=1863326&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.10/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/AbstractDataRecordAccessProviderTest.java
 (original)
+++ 
jackrabbit/oak/branches/1.10/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/AbstractDataRecordAccessProviderTest.java
 Thu Jul 18 17:07:38 2019
@@ -81,10 +81,20 @@ public abstract class AbstractDataRecord
     // Direct download tests
     //
     @Test
-    public void testGetDownloadURIProvidesValidURI() {
-        DataIdentifier id = new DataIdentifier("testIdentifier");
-        URI uri = getDataStore().getDownloadURI(id, 
DataRecordDownloadOptions.DEFAULT);
-        assertNotNull(uri);
+    public void testGetDownloadURIProvidesValidURIIT() throws 
DataStoreException {
+        DataRecord record = null;
+        ConfigurableDataRecordAccessProvider dataStore = getDataStore();
+        try {
+            InputStream testStream = randomStream(0, 256);
+            record = doSynchronousAddRecord((DataStore) dataStore, testStream);
+            DataIdentifier id = record.getIdentifier();
+            URI uri = getDataStore().getDownloadURI(id, 
DataRecordDownloadOptions.DEFAULT);
+            assertNotNull(uri);
+        } finally {
+            if (null != record) {
+                doDeleteRecord((DataStore) dataStore, record.getIdentifier());
+            }
+        }
     }
 
     @Test
@@ -219,6 +229,20 @@ public abstract class AbstractDataRecord
         }
     }
 
+    @Test
+    public void testGetDownloadURINonexistentBlobFailsIT() throws 
DataStoreException {
+        ConfigurableDataRecordAccessProvider dataStore = getDataStore();
+        InputStream testStream = randomStream(0, 256);
+
+        DataRecord record = doSynchronousAddRecord((DataStore) dataStore, 
testStream);
+
+        doDeleteRecord((DataStore) dataStore, record.getIdentifier());
+
+        URI uri = dataStore.getDownloadURI(record.getIdentifier(), 
DataRecordDownloadOptions.DEFAULT);
+
+        assertNull(uri);
+    }
+
     //
     // Direct upload tests
     //

Modified: 
jackrabbit/oak/branches/1.10/oak-doc/src/site/markdown/features/direct-binary-access.md
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.10/oak-doc/src/site/markdown/features/direct-binary-access.md?rev=1863326&r1=1863325&r2=1863326&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.10/oak-doc/src/site/markdown/features/direct-binary-access.md
 (original)
+++ 
jackrabbit/oak/branches/1.10/oak-doc/src/site/markdown/features/direct-binary-access.md
 Thu Jul 18 17:07:38 2019
@@ -106,6 +106,11 @@ if (binary instanceof BinaryDownload) {
 
 Please note that only `Binary` objects returned from `Property.getBinary()`, 
`Property.getValue().getBinary()` or `Property.getValues() ... getBinary()` 
will support a functional `BinaryDownload`.
 
+Also note that clients should always check whether the URI returned from the 
`getURI()` call is null.  A null return value generally indicates that the 
feature is not available.  But this situation is also possible in two other 
cases:
+
+* If the binary is stored in-line in the node store.  If the binary is smaller 
than the minimum upload size, it will be stored in the node store instead of in 
cloud blob storage, and thus a direct download URI cannot be provided.
+* If the data store implementation is using asynchronous uploads and the 
binary is still in cache.  If a client adds a binary via the repository (i.e. 
not using the direct binary upload feature) and then immediately requests a 
download URI for it, it is possible that the binary is still in cache and not 
yet uploaded to cloud storage, and thus a direct download URI cannot be 
provided.
+
 ### Upload
 
 The direct binary upload process is split into 3 phases:
@@ -178,6 +183,8 @@ public class InitiateUploadServlet exten
 }
 ```
 
+Clients should always check whether the `BinaryUpload` returned from 
`valueFactory.initiateBinaryUpload()` is null, and also should handle the case 
where no upload URIs are returned.  Either situation indicates that the feature 
is not supported.
+
 #### 2. Upload
 
 The remote client will upload using the instructions according to the [upload 
algorithm described in 
BinaryUpload](http://jackrabbit.apache.org/api/trunk/org/apache/jackrabbit/api/binary/BinaryUpload.html).


Reply via email to