You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ma...@apache.org on 2020/01/10 04:38:46 UTC

svn commit: r1872572 - in /jackrabbit/oak/trunk: oak-api/src/main/java/org/apache/jackrabbit/oak/api/blob/ oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/ oak-blob-cloud-azure/src/test/java/org/apache/jackrabb...

Author: mattryan
Date: Fri Jan 10 04:38:45 2020
New Revision: 1872572

URL: http://svn.apache.org/viewvc?rev=1872572&view=rev
Log:
OAK-8280: Add support to request ignoring domain override for signed URIs.

This change introduces BlobUploadOptions so options can be requested for
both upload and download URIs, and adds the option for both URI requests
to ignore the domain override if one is set.

Added:
    jackrabbit/oak/trunk/oak-api/src/main/java/org/apache/jackrabbit/oak/api/blob/BlobUploadOptions.java
    jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordUploadOptions.java
    jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/package-info.java
    jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordUploadOptionsTest.java
    jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/BinaryUploadOptions.java
Modified:
    jackrabbit/oak/trunk/oak-api/src/main/java/org/apache/jackrabbit/oak/api/blob/BlobAccessProvider.java
    jackrabbit/oak/trunk/oak-api/src/main/java/org/apache/jackrabbit/oak/api/blob/BlobDownloadOptions.java
    jackrabbit/oak/trunk/oak-api/src/main/java/org/apache/jackrabbit/oak/api/blob/package-info.java
    jackrabbit/oak/trunk/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureBlobStoreBackend.java
    jackrabbit/oak/trunk/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureDataStore.java
    jackrabbit/oak/trunk/oak-blob-cloud-azure/src/test/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureDataRecordAccessProviderCDNTest.java
    jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3DataStore.java
    jackrabbit/oak/trunk/oak-blob-plugins/pom.xml
    jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/DataStoreBlobStore.java
    jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordAccessProvider.java
    jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptions.java
    jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/BlobGCTest.java
    jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/BlobStoreStatsTestableFileDataStore.java
    jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptionsTest.java
    jackrabbit/oak/trunk/oak-doc/src/site/markdown/features/direct-binary-access.md
    jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/JackrabbitValueFactory.java
    jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/BinaryDownloadOptions.java
    jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/package-info.java
    jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/package-info.java
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/BinaryAccessTest.java
    jackrabbit/oak/trunk/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/plugins/value/jcr/PartialValueFactory.java
    jackrabbit/oak/trunk/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/plugins/value/jcr/ValueFactoryImpl.java

Modified: jackrabbit/oak/trunk/oak-api/src/main/java/org/apache/jackrabbit/oak/api/blob/BlobAccessProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-api/src/main/java/org/apache/jackrabbit/oak/api/blob/BlobAccessProvider.java?rev=1872572&r1=1872571&r2=1872572&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-api/src/main/java/org/apache/jackrabbit/oak/api/blob/BlobAccessProvider.java (original)
+++ jackrabbit/oak/trunk/oak-api/src/main/java/org/apache/jackrabbit/oak/api/blob/BlobAccessProvider.java Fri Jan 10 04:38:45 2020
@@ -79,6 +79,55 @@ public interface BlobAccessProvider {
             throws IllegalArgumentException;
 
     /**
+     * Begin a transaction to perform a direct blob upload to a storage
+     * location. This method will throw {@link IllegalArgumentException} if no
+     * valid upload can be arranged with the arguments specified. E.g. the max
+     * upload size specified divided by the number of URIs requested indicates
+     * the minimum size of each upload. If that size exceeds the maximum upload
+     * size supported by the service provider, {@link IllegalArgumentException}
+     * is thrown.
+     * <p>
+     * Each service provider has specific limitations with regard to maximum
+     * upload sizes, maximum overall blob sizes, numbers of URIs in multi-part
+     * uploads, etc. which can lead to {@link IllegalArgumentException} being
+     * thrown. You should consult the documentation for your specific service
+     * provider for details.
+     * <p>
+     * Beyond service provider limitations, the implementation may also choose
+     * to enforce its own limitations and may throw this exception based on
+     * those limitations. Configuration may also be used to set limitations so
+     * this exception may be thrown when configuration parameters are exceeded.
+     *
+     * @param maxUploadSizeInBytes the largest size of the blob to be
+     *         uploaded, in bytes, based on the caller's best guess.  If the
+     *         actual size of the file to be uploaded is known, that value
+     *         should be used.
+     * @param maxNumberOfURIs the maximum number of URIs the client is able to
+     *         accept. If the client does not support multi-part uploading, this
+     *         value should be 1. Note that the implementing class is not
+     *         required to support multi-part uploading so it may return only a
+     *         single upload URI regardless of the value passed in for this
+     *         parameter.  If the client is able to accept any number of URIs, a
+     *         value of -1 may be passed in to indicate that the implementation
+     *         is free to return as many URIs as it desires.
+     * @param options an instance of {@link BlobUploadOptions} which allows the
+     *                caller to specify any desired upload URI options.
+     * @return A {@link BlobUpload} referencing this direct upload, or
+     *         {@code null} if the underlying implementation doesn't support
+     *         direct uploading.
+     * @throws IllegalArgumentException if {@code maxUploadSizeInBytes} is not
+     *         a positive value, or if {@code maxNumberOfURIs} is not either a
+     *         positive value or -1, or if the upload cannot be completed as
+     *         requested, due to a mismatch between the request parameters and
+     *         the capabilities of the service provider or the implementation.
+     */
+    @Nullable
+    BlobUpload initiateBlobUpload(long maxUploadSizeInBytes,
+                                  int maxNumberOfURIs,
+                                  @NotNull final BlobUploadOptions options)
+            throws IllegalArgumentException;
+
+    /**
      * Complete a transaction for uploading a blob to a storage location via
      * direct blob upload.
      * <p>

Modified: jackrabbit/oak/trunk/oak-api/src/main/java/org/apache/jackrabbit/oak/api/blob/BlobDownloadOptions.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-api/src/main/java/org/apache/jackrabbit/oak/api/blob/BlobDownloadOptions.java?rev=1872572&r1=1872571&r2=1872572&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-api/src/main/java/org/apache/jackrabbit/oak/api/blob/BlobDownloadOptions.java (original)
+++ jackrabbit/oak/trunk/oak-api/src/main/java/org/apache/jackrabbit/oak/api/blob/BlobDownloadOptions.java Fri Jan 10 04:38:45 2020
@@ -38,6 +38,7 @@ public class BlobDownloadOptions {
     private final String characterEncoding;
     private final String fileName;
     private final String dispositionType;
+    private boolean domainOverrideIgnored = false;
 
     public static final BlobDownloadOptions DEFAULT = new BlobDownloadOptions();
 
@@ -57,6 +58,25 @@ public class BlobDownloadOptions {
                                @Nullable String characterEncoding,
                                @Nullable String fileName,
                                @NotNull String dispositionType) {
+        this(mediaType, characterEncoding, fileName, dispositionType, false);
+    }
+
+    /**
+     * Creates new download options.
+     *
+     * @param mediaType the internet media type for the blob.
+     * @param characterEncoding the character encoding for the blob.
+     * @param fileName the file name for the blob.
+     * @param dispositionType the disposition type.
+     * @param domainOverrideIgnored true if any configured domain override
+     *                              should be ignored when generating URIs;
+     *                              false otherwise.
+     */
+    public BlobDownloadOptions(@Nullable String mediaType,
+                               @Nullable String characterEncoding,
+                               @Nullable String fileName,
+                               @NotNull String dispositionType,
+                               boolean domainOverrideIgnored) {
         if (dispositionType == null) {
             throw new NullPointerException("dispositionType must not be null");
         }
@@ -64,6 +84,7 @@ public class BlobDownloadOptions {
         this.characterEncoding = characterEncoding;
         this.fileName = fileName;
         this.dispositionType = dispositionType;
+        this.domainOverrideIgnored = domainOverrideIgnored;
     }
 
     /**
@@ -115,4 +136,12 @@ public class BlobDownloadOptions {
     public String getDispositionType() {
         return dispositionType;
     }
+
+    /**
+     * Indicates whether the data store should ignore any provided download
+     * domain override configuration value when generating the signed URI.
+     *
+     * @return true if the domain override should be ignored; false otherwise.
+     */
+    public boolean isDomainOverrideIgnored() { return domainOverrideIgnored; }
 }

Added: jackrabbit/oak/trunk/oak-api/src/main/java/org/apache/jackrabbit/oak/api/blob/BlobUploadOptions.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-api/src/main/java/org/apache/jackrabbit/oak/api/blob/BlobUploadOptions.java?rev=1872572&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-api/src/main/java/org/apache/jackrabbit/oak/api/blob/BlobUploadOptions.java (added)
+++ jackrabbit/oak/trunk/oak-api/src/main/java/org/apache/jackrabbit/oak/api/blob/BlobUploadOptions.java Fri Jan 10 04:38:45 2020
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.jackrabbit.oak.api.blob;
+
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * Download options to be provided to a call to {@link
+ * BlobAccessProvider#initiateBlobUpload(long, int, BlobUploadOptions)}.
+ * <p>
+ * This object is an internal corollary to {@code
+ * org.apache.jackrabbit.api.binary.BinaryUploadOptions}.
+ */
+@ProviderType
+public class BlobUploadOptions {
+    private boolean domainOverrideIgnored = false;
+
+    public static final BlobUploadOptions DEFAULT = new BlobUploadOptions();
+
+    private BlobUploadOptions() {
+        this(false);
+    }
+
+    /**
+     * Creates a new upload options instance.
+     *
+     * @param domainOverrideIgnored true if any configured domain override
+     *                              should be ignored when generating URIs;
+     *                              false otherwise.
+     */
+    public BlobUploadOptions(boolean domainOverrideIgnored) {
+        this.domainOverrideIgnored = domainOverrideIgnored;
+    }
+
+    /**
+     * Get the setting to determine if any configured domain override should be
+     * ignored when generating URIs.
+     *
+     * Default behavior is to honor (i.e. not ignore) any configured domain
+     * override value (false).
+     *
+     * @return true to ignore the domain override; false otherwise.
+     */
+    public boolean isDomainOverrideIgnored() {
+        return domainOverrideIgnored;
+    }
+}

Modified: jackrabbit/oak/trunk/oak-api/src/main/java/org/apache/jackrabbit/oak/api/blob/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-api/src/main/java/org/apache/jackrabbit/oak/api/blob/package-info.java?rev=1872572&r1=1872571&r2=1872572&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-api/src/main/java/org/apache/jackrabbit/oak/api/blob/package-info.java (original)
+++ jackrabbit/oak/trunk/oak-api/src/main/java/org/apache/jackrabbit/oak/api/blob/package-info.java Fri Jan 10 04:38:45 2020
@@ -20,7 +20,7 @@
 /**
  * Package related to direct upload/download of blobs.
  */
-@Version("1.0.0")
+@Version("1.1.0")
 package org.apache.jackrabbit.oak.api.blob;
 
 import org.osgi.annotation.versioning.Version;

Modified: jackrabbit/oak/trunk/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/trunk/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureBlobStoreBackend.java?rev=1872572&r1=1872571&r2=1872572&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureBlobStoreBackend.java (original)
+++ jackrabbit/oak/trunk/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureBlobStoreBackend.java Fri Jan 10 04:38:45 2020
@@ -78,6 +78,7 @@ import org.apache.jackrabbit.core.data.D
 import org.apache.jackrabbit.core.data.DataStoreException;
 import org.apache.jackrabbit.oak.commons.PropertiesUtil;
 import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUploadException;
+import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUploadOptions;
 import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUploadToken;
 import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordDownloadOptions;
 import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUpload;
@@ -818,7 +819,7 @@ public class AzureBlobStoreBackend exten
                     headers.setContentDisposition(contentDisposition);
                 }
 
-                String domain = getDirectDownloadBlobStorageDomain();
+                String domain = getDirectDownloadBlobStorageDomain(downloadOptions.isDomainOverrideIgnored());
                 if (null == domain) {
                     throw new NullPointerException("Could not determine domain for direct download");
                 }
@@ -847,7 +848,7 @@ public class AzureBlobStoreBackend exten
         );
     }
 
-    DataRecordUpload initiateHttpUpload(long maxUploadSizeInBytes, int maxNumberOfURIs) {
+    DataRecordUpload initiateHttpUpload(long maxUploadSizeInBytes, int maxNumberOfURIs, @NotNull final DataRecordUploadOptions options) {
         List<URI> uploadPartURIs = Lists.newArrayList();
         long minPartSize = MIN_MULTIPART_UPLOAD_PART_SIZE;
         long maxPartSize = MAX_MULTIPART_UPLOAD_PART_SIZE;
@@ -923,7 +924,7 @@ public class AzureBlobStoreBackend exten
             }
 
             String key = getKeyName(newIdentifier);
-            String domain = getDirectUploadBlobStorageDomain();
+            String domain = getDirectUploadBlobStorageDomain(options.isDomainOverrideIgnored());
             if (null == domain) {
                 throw new NullPointerException("Could not determine domain for direct upload");
             }
@@ -1047,16 +1048,20 @@ public class AzureBlobStoreBackend exten
         return String.format("%s.blob.core.windows.net", accountName);
     }
 
-    private String getDirectDownloadBlobStorageDomain() {
-        String domain = properties.getProperty(AzureConstants.PRESIGNED_HTTP_DOWNLOAD_URI_DOMAIN_OVERRIDE, null);
+    private String getDirectDownloadBlobStorageDomain(boolean ignoreDomainOverride) {
+        String domain = ignoreDomainOverride
+                ? getDefaultBlobStorageDomain()
+                : properties.getProperty(AzureConstants.PRESIGNED_HTTP_DOWNLOAD_URI_DOMAIN_OVERRIDE, null);
         if (Strings.isNullOrEmpty(domain)) {
             domain = getDefaultBlobStorageDomain();
         }
         return domain;
     }
 
-    private String getDirectUploadBlobStorageDomain() {
-        String domain = properties.getProperty(AzureConstants.PRESIGNED_HTTP_UPLOAD_URI_DOMAIN_OVERRIDE, null);
+    private String getDirectUploadBlobStorageDomain(boolean ignoreDomainOverride) {
+        String domain = ignoreDomainOverride
+                ? getDefaultBlobStorageDomain()
+                : properties.getProperty(AzureConstants.PRESIGNED_HTTP_UPLOAD_URI_DOMAIN_OVERRIDE, null);
         if (Strings.isNullOrEmpty(domain)) {
             domain = getDefaultBlobStorageDomain();
         }

Modified: jackrabbit/oak/trunk/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureDataStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureDataStore.java?rev=1872572&r1=1872571&r2=1872572&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureDataStore.java (original)
+++ jackrabbit/oak/trunk/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureDataStore.java Fri Jan 10 04:38:45 2020
@@ -30,6 +30,7 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUploadException;
 import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordDownloadOptions;
 import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUpload;
+import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUploadOptions;
 import org.apache.jackrabbit.oak.spi.blob.AbstractSharedBackend;
 import org.apache.jackrabbit.oak.spi.blob.SharedBackend;
 import org.jetbrains.annotations.NotNull;
@@ -87,10 +88,17 @@ public class AzureDataStore extends Abst
     @Override
     public DataRecordUpload initiateDataRecordUpload(long maxUploadSizeInBytes, int maxNumberOfURIs)
             throws IllegalArgumentException, DataRecordUploadException {
+        return initiateDataRecordUpload(maxUploadSizeInBytes, maxNumberOfURIs, DataRecordUploadOptions.DEFAULT);
+    }
+
+    @Nullable
+    @Override
+    public DataRecordUpload initiateDataRecordUpload(long maxUploadSizeInBytes, int maxNumberOfURIs, @NotNull final DataRecordUploadOptions options)
+            throws IllegalArgumentException, DataRecordUploadException {
         if (null == azureBlobStoreBackend) {
             throw new DataRecordUploadException("Backend not initialized");
         }
-        return azureBlobStoreBackend.initiateHttpUpload(maxUploadSizeInBytes, maxNumberOfURIs);
+        return azureBlobStoreBackend.initiateHttpUpload(maxUploadSizeInBytes, maxNumberOfURIs, options);
     }
 
     @NotNull

Modified: jackrabbit/oak/trunk/oak-blob-cloud-azure/src/test/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureDataRecordAccessProviderCDNTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-cloud-azure/src/test/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureDataRecordAccessProviderCDNTest.java?rev=1872572&r1=1872571&r2=1872572&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-blob-cloud-azure/src/test/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureDataRecordAccessProviderCDNTest.java (original)
+++ jackrabbit/oak/trunk/oak-blob-cloud-azure/src/test/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureDataRecordAccessProviderCDNTest.java Fri Jan 10 04:38:45 2020
@@ -23,6 +23,7 @@ import static org.apache.jackrabbit.oak.
 import static org.apache.jackrabbit.oak.blob.cloud.azure.blobstorage.AzureConstants.PRESIGNED_HTTP_DOWNLOAD_URI_VERIFY_EXISTS;
 import static org.apache.jackrabbit.oak.blob.cloud.azure.blobstorage.AzureConstants.PRESIGNED_HTTP_UPLOAD_URI_DOMAIN_OVERRIDE;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
@@ -33,9 +34,12 @@ import java.util.Properties;
 
 import com.google.common.base.Strings;
 import org.apache.jackrabbit.core.data.DataIdentifier;
+import org.apache.jackrabbit.oak.api.blob.BlobDownloadOptions;
+import org.apache.jackrabbit.oak.api.blob.BlobUploadOptions;
 import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.ConfigurableDataRecordAccessProvider;
 import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordDownloadOptions;
 import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUpload;
+import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUploadOptions;
 import org.jetbrains.annotations.NotNull;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
@@ -92,12 +96,16 @@ public class AzureDataRecordAccessProvid
         return createDataStore(AzureDataStoreUtils.getDirectAccessDataStoreProperties(overrideProperties));
     }
 
+    private ConfigurableDataRecordAccessProvider getCDNEnabledDataStore() throws Exception {
+        Properties properties = new Properties();
+        properties.put(PRESIGNED_HTTP_DOWNLOAD_URI_VERIFY_EXISTS, "false");
+        return getDataStore(properties);
+    }
+
     // CDN Tests
     @Test
     public void testCDNDownloadURIContainsDownloadDomain() throws Exception {
-        Properties properties = new Properties();
-        properties.put(PRESIGNED_HTTP_DOWNLOAD_URI_VERIFY_EXISTS, "false");
-        ConfigurableDataRecordAccessProvider ds = getDataStore(properties);
+        ConfigurableDataRecordAccessProvider ds = getCDNEnabledDataStore();
         DataIdentifier id = new DataIdentifier("identifier");
         URI downloadUri = ds.getDownloadURI(id, DataRecordDownloadOptions.DEFAULT);
         assertNotNull(downloadUri);
@@ -107,7 +115,6 @@ public class AzureDataRecordAccessProvid
     @Test
     public void testCDNUploadURIContainsUploadDomain() throws Exception {
         Properties properties = new Properties();
-        properties.put(PRESIGNED_HTTP_DOWNLOAD_URI_VERIFY_EXISTS, "false");
         ConfigurableDataRecordAccessProvider ds = getDataStore(properties);
         DataRecordUpload upload = ds.initiateDataRecordUpload(ONE_MB, 10);
         assertNotNull(upload);
@@ -116,4 +123,39 @@ public class AzureDataRecordAccessProvid
             assertEquals(UPLOAD_URI_DOMAIN, uri.getHost());
         }
     }
+
+    @Test
+    public void testVetoDownloadDomainOverride() throws Exception {
+        ConfigurableDataRecordAccessProvider ds = getCDNEnabledDataStore();
+        DataIdentifier id = new DataIdentifier("identifier");
+        DataRecordDownloadOptions options =
+                DataRecordDownloadOptions.fromBlobDownloadOptions(
+                        new BlobDownloadOptions(null, null, null, "inline", true)
+                );
+        URI downloadUri = ds.getDownloadURI(id, options);
+        assertNotNull(downloadUri);
+        assertNotEquals(DOWNLOAD_URI_DOMAIN, downloadUri.getHost());
+
+        Properties properties = AzureDataStoreUtils.getDirectAccessDataStoreProperties();
+        String accountName = properties.getProperty(AzureConstants.AZURE_STORAGE_ACCOUNT_NAME, null);
+        assertNotNull(accountName);
+        assertEquals(String.format("%s.blob.core.windows.net", accountName), downloadUri.getHost());
+    }
+
+    @Test
+    public void testVetoUploadDomainOverride() throws Exception {
+        ConfigurableDataRecordAccessProvider ds = getCDNEnabledDataStore();
+        DataRecordUpload upload = ds.initiateDataRecordUpload(ONE_MB, 10,
+                DataRecordUploadOptions.fromBlobUploadOptions(new BlobUploadOptions(true)));
+        assertNotNull(upload);
+        assertTrue(upload.getUploadURIs().size() > 0);
+
+        Properties properties = AzureDataStoreUtils.getDirectAccessDataStoreProperties();
+        String accountName = properties.getProperty(AzureConstants.AZURE_STORAGE_ACCOUNT_NAME, null);
+        assertNotNull(accountName);
+        String defaultDomain = String.format("%s.blob.core.windows.net", accountName);
+        for (URI uri : upload.getUploadURIs()) {
+            assertEquals(defaultDomain, uri.getHost());
+        }
+    }
 }

Modified: jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3DataStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3DataStore.java?rev=1872572&r1=1872571&r2=1872572&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3DataStore.java (original)
+++ jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3DataStore.java Fri Jan 10 04:38:45 2020
@@ -27,6 +27,7 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUploadException;
 import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordDownloadOptions;
 import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUpload;
+import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUploadOptions;
 import org.apache.jackrabbit.oak.spi.blob.AbstractSharedBackend;
 import org.apache.jackrabbit.oak.spi.blob.SharedBackend;
 import org.jetbrains.annotations.NotNull;
@@ -99,6 +100,13 @@ public class S3DataStore extends Abstrac
     @Override
     public DataRecordUpload initiateDataRecordUpload(long maxUploadSizeInBytes, int maxNumberOfURIs)
             throws IllegalArgumentException, DataRecordUploadException {
+        return initiateDataRecordUpload(maxUploadSizeInBytes, maxNumberOfURIs, DataRecordUploadOptions.DEFAULT);
+    }
+
+    @Nullable
+    @Override
+    public DataRecordUpload initiateDataRecordUpload(long maxUploadSizeInBytes, int maxNumberOfURIs, @NotNull final DataRecordUploadOptions options)
+        throws IllegalArgumentException, DataRecordUploadException {
         if (null == s3Backend) {
             throw new DataRecordUploadException("Backend not initialized");
         }

Modified: jackrabbit/oak/trunk/oak-blob-plugins/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-plugins/pom.xml?rev=1872572&r1=1872571&r2=1872572&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-blob-plugins/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-blob-plugins/pom.xml Fri Jan 10 04:38:45 2020
@@ -199,6 +199,10 @@
       <classifier>tests</classifier>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.annotation</artifactId>
+    </dependency>
   </dependencies>
 
 </project>

Modified: jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/DataStoreBlobStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/DataStoreBlobStore.java?rev=1872572&r1=1872571&r2=1872572&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/DataStoreBlobStore.java (original)
+++ jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/DataStoreBlobStore.java Fri Jan 10 04:38:45 2020
@@ -61,6 +61,7 @@ import org.apache.jackrabbit.oak.api.Blo
 import org.apache.jackrabbit.oak.api.blob.BlobAccessProvider;
 import org.apache.jackrabbit.oak.api.blob.BlobDownloadOptions;
 import org.apache.jackrabbit.oak.api.blob.BlobUpload;
+import org.apache.jackrabbit.oak.api.blob.BlobUploadOptions;
 import org.apache.jackrabbit.oak.cache.CacheLIRS;
 import org.apache.jackrabbit.oak.cache.CacheStats;
 import org.apache.jackrabbit.oak.commons.StringUtils;
@@ -72,6 +73,7 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordDownloadOptions;
 import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUpload;
 import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUploadException;
+import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUploadOptions;
 import org.apache.jackrabbit.oak.spi.blob.BlobOptions;
 import org.apache.jackrabbit.oak.spi.blob.BlobStore;
 import org.apache.jackrabbit.oak.spi.blob.GarbageCollectableBlobStore;
@@ -943,13 +945,21 @@ public class DataStoreBlobStore
     @Override
     public BlobUpload initiateBlobUpload(long maxUploadSizeInBytes, int maxNumberOfURIs)
             throws IllegalArgumentException {
+        return initiateBlobUpload(maxUploadSizeInBytes, maxNumberOfURIs, BlobUploadOptions.DEFAULT);
+    }
+
+    @Nullable
+    @Override
+    public BlobUpload initiateBlobUpload(long maxUploadSizeInBytes, int maxNumberOfURIs, @NotNull final BlobUploadOptions options)
+            throws IllegalArgumentException {
         if (delegate instanceof DataRecordAccessProvider) {
             try {
                 long start = System.nanoTime();
 
                 DataRecordAccessProvider provider = (DataRecordAccessProvider) this.delegate;
 
-                DataRecordUpload upload = provider.initiateDataRecordUpload(maxUploadSizeInBytes, maxNumberOfURIs);
+                DataRecordUpload upload = provider.initiateDataRecordUpload(maxUploadSizeInBytes, maxNumberOfURIs,
+                        DataRecordUploadOptions.fromBlobUploadOptions(options));
 
                 if (upload == null) {
                     if (stats instanceof ExtendedBlobStatsCollector) {

Modified: jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordAccessProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordAccessProvider.java?rev=1872572&r1=1872571&r2=1872572&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordAccessProvider.java (original)
+++ jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordAccessProvider.java Fri Jan 10 04:38:45 2020
@@ -83,6 +83,38 @@ public interface DataRecordAccessProvide
             throws IllegalArgumentException, DataRecordUploadException;
 
     /**
+     * Begin a transaction to perform a direct binary upload to the storage
+     * location.
+     *
+     * @param maxUploadSizeInBytes - the largest size of the binary to be
+     *        uploaded, in bytes, based on the caller's best guess.  If the
+     *        actual size of the file to be uploaded is known, that value should
+     *        be used.
+     * @param maxNumberOfURIs - the maximum number of URIs the client is able to
+     *        accept.  If the caller does not support multi-part uploading, this
+     *        value should be 1.  Note that the implementing class is not
+     *        required to support multi-part uploading so it may return only a
+     *        single upload URI regardless of the value passed in for this
+     *        parameter.  A caller may also pass in -1 to indicate that it is
+     *        able to accept any number of URIs.  Any other negative number or
+     *        0 may result in {@link IllegalArgumentException}.
+     * @param options - a {@link DataRecordUploadOptions} instance containing
+     *                any caller-specified options for upload URI generation.
+     * @return A {@link DataRecordUpload} referencing this direct upload,
+     *         or {@code null} if the implementation does not support direct
+     *         upload.
+     * @throws IllegalArgumentException if the service provider or
+     *         implementation cannot support the requested upload.
+     * @throws DataRecordUploadException if the upload cannot be completed as
+     *         requested.
+     */
+    @Nullable
+    DataRecordUpload initiateDataRecordUpload(long maxUploadSizeInBytes,
+                                              int maxNumberOfURIs,
+                                              DataRecordUploadOptions options)
+            throws IllegalArgumentException, DataRecordUploadException;
+
+    /**
      * Completes the transaction to perform a direct binary upload.  This method
      * verifies that the uploaded binary has been created and is now
      * referenceable.  For some providers doing multi-part upload, this also

Modified: jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptions.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptions.java?rev=1872572&r1=1872571&r2=1872572&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptions.java (original)
+++ jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptions.java Fri Jan 10 04:38:45 2020
@@ -61,7 +61,8 @@ public class DataRecordDownloadOptions {
                 downloadOptions.getMediaType(),
                 downloadOptions.getCharacterEncoding(),
                 downloadOptions.getFileName(),
-                downloadOptions.getDispositionType()
+                downloadOptions.getDispositionType(),
+                downloadOptions.isDomainOverrideIgnored()
         );
     }
 
@@ -74,12 +75,14 @@ public class DataRecordDownloadOptions {
             new DataRecordDownloadOptions(null,
                     null,
                     null,
-                    DISPOSITION_TYPE_INLINE);
+                    DISPOSITION_TYPE_INLINE,
+                    false);
 
     private final String mediaType;
     private final String characterEncoding;
     private final String fileName;
     private final String dispositionType;
+    private boolean domainOverrideIgnored = false;
 
     private String contentTypeHeader = null;
     private String contentDispositionHeader = null;
@@ -87,13 +90,15 @@ public class DataRecordDownloadOptions {
     private DataRecordDownloadOptions(final String mediaType,
                                       final String characterEncoding,
                                       final String fileName,
-                                      final String dispositionType) {
+                                      final String dispositionType,
+                                      boolean domainOverrideIgnored) {
         this.mediaType = mediaType;
         this.characterEncoding = characterEncoding;
         this.fileName = fileName;
         this.dispositionType = Strings.isNullOrEmpty(dispositionType) ?
                 DISPOSITION_TYPE_INLINE :
                 dispositionType;
+        this.domainOverrideIgnored = domainOverrideIgnored;
     }
 
     /**
@@ -211,4 +216,12 @@ public class DataRecordDownloadOptions {
     public String getDispositionType() {
         return dispositionType;
     }
+
+    /**
+     * Indicates whether the data store should ignore any configured download
+     * domain override value when generating the signed download URI.
+     *
+     * @return true if the domain override should be ignored; false otherwise.
+     */
+    public boolean isDomainOverrideIgnored() { return domainOverrideIgnored; }
 }

Added: jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordUploadOptions.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordUploadOptions.java?rev=1872572&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordUploadOptions.java (added)
+++ jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordUploadOptions.java Fri Jan 10 04:38:45 2020
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess;
+
+import org.apache.jackrabbit.oak.api.blob.BlobUploadOptions;
+import org.jetbrains.annotations.NotNull;
+
+public class DataRecordUploadOptions {
+    private boolean domainOverrideIgnored;
+
+    public static DataRecordUploadOptions fromBlobUploadOptions(@NotNull final BlobUploadOptions options) {
+        return new DataRecordUploadOptions(options.isDomainOverrideIgnored());
+    }
+
+    public static DataRecordUploadOptions DEFAULT = new DataRecordUploadOptions(false);
+
+    private DataRecordUploadOptions(boolean domainOverrideIgnored) {
+        this.domainOverrideIgnored = domainOverrideIgnored;
+    }
+
+    public boolean isDomainOverrideIgnored() {
+        return domainOverrideIgnored;
+    }
+}

Added: jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/package-info.java?rev=1872572&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/package-info.java (added)
+++ jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/package-info.java Fri Jan 10 04:38:45 2020
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Package related to direct upload/download of data records.
+ */
+@Version("1.0.0")
+package org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess;
+
+import org.osgi.annotation.versioning.Version;
+

Modified: jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/BlobGCTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/BlobGCTest.java?rev=1872572&r1=1872571&r2=1872572&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/BlobGCTest.java (original)
+++ jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/BlobGCTest.java Fri Jan 10 04:38:45 2020
@@ -19,6 +19,22 @@
 
 package org.apache.jackrabbit.oak.plugins.blob;
 
+import static org.apache.commons.codec.binary.Hex.encodeHexString;
+import static org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.CONSISTENCY_NAME;
+import static org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.FINISH_FAILURE;
+import static org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.NAME;
+import static org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.NUM_BLOBS_DELETED;
+import static org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.NUM_CANDIDATES;
+import static org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.START;
+import static org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.TOTAL_SIZE_DELETED;
+import static org.apache.jackrabbit.oak.plugins.blob.OperationsStatsMBean.TYPE;
+import static org.apache.jackrabbit.oak.plugins.blob.datastore.DataStoreUtils.randomStream;
+import static org.apache.jackrabbit.oak.plugins.blob.datastore.SharedDataStoreUtils.SharedStoreRecordType.REPOSITORY;
+import static org.apache.jackrabbit.oak.stats.StatsOptions.METRICS_ONLY;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
 import java.io.ByteArrayInputStream;
 import java.io.Closeable;
 import java.io.File;
@@ -72,6 +88,7 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordDownloadOptions;
 import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUpload;
 import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUploadException;
+import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUploadOptions;
 import org.apache.jackrabbit.oak.plugins.memory.ArrayBasedBlob;
 import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore;
 import org.apache.jackrabbit.oak.spi.blob.BlobStore;
@@ -98,22 +115,6 @@ import org.mockito.internal.util.collect
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import static org.apache.commons.codec.binary.Hex.encodeHexString;
-import static org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.CONSISTENCY_NAME;
-import static org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.FINISH_FAILURE;
-import static org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.NAME;
-import static org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.NUM_BLOBS_DELETED;
-import static org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.NUM_CANDIDATES;
-import static org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.START;
-import static org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.TOTAL_SIZE_DELETED;
-import static org.apache.jackrabbit.oak.plugins.blob.OperationsStatsMBean.TYPE;
-import static org.apache.jackrabbit.oak.plugins.blob.datastore.DataStoreUtils.randomStream;
-import static org.apache.jackrabbit.oak.plugins.blob.datastore.SharedDataStoreUtils.SharedStoreRecordType.REPOSITORY;
-import static org.apache.jackrabbit.oak.stats.StatsOptions.METRICS_ONLY;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
 /**
  * Generic class for BlobGC tests which uses custom MemoryNodeStore as well as a memory NodeStore.
  */
@@ -864,7 +865,13 @@ public class BlobGCTest {
 
         @Override
         public @Nullable DataRecordUpload initiateDataRecordUpload(long maxUploadSizeInBytes, int maxNumberOfURIs)
-            throws IllegalArgumentException, DataRecordUploadException {
+                throws IllegalArgumentException, DataRecordUploadException {
+            return initiateDataRecordUpload(maxUploadSizeInBytes, maxNumberOfURIs, DataRecordUploadOptions.DEFAULT);
+        }
+
+        @Override
+        public @Nullable DataRecordUpload initiateDataRecordUpload(long maxUploadSizeInBytes, int maxNumberOfURIs, @NotNull final DataRecordUploadOptions options)
+                throws IllegalArgumentException, DataRecordUploadException {
             String upToken = UUID.randomUUID().toString();
             Random rand = new Random();
             InputStream stream = randomStream(rand.nextInt(1000), 100);

Modified: jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/BlobStoreStatsTestableFileDataStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/BlobStoreStatsTestableFileDataStore.java?rev=1872572&r1=1872571&r2=1872572&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/BlobStoreStatsTestableFileDataStore.java (original)
+++ jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/BlobStoreStatsTestableFileDataStore.java Fri Jan 10 04:38:45 2020
@@ -32,6 +32,7 @@ import org.apache.jackrabbit.core.data.D
 import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordAccessProvider;
 import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordDownloadOptions;
 import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUpload;
+import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUploadOptions;
 import org.apache.jackrabbit.oak.spi.blob.BlobOptions;
 import org.apache.jackrabbit.oak.spi.blob.stats.BlobStatsCollector;
 import org.apache.jackrabbit.oak.spi.blob.stats.StatsCollectingStreams;
@@ -454,6 +455,12 @@ public class BlobStoreStatsTestableFileD
 
     @Override
     public DataRecordUpload initiateDataRecordUpload(long maxUploadSizeInBytes, int maxNumberOfURIs) throws IllegalArgumentException {
+        return initiateDataRecordUpload(maxUploadSizeInBytes, maxNumberOfURIs, DataRecordUploadOptions.DEFAULT);
+    }
+
+    @Override
+    public DataRecordUpload initiateDataRecordUpload(long maxUploadSizeInBytes, int maxNumberOfURIs, @NotNull final DataRecordUploadOptions options)
+            throws IllegalArgumentException {
         delay(initUploadDelay);
         if (withInitUploadError) throw new IllegalArgumentException();
         return new DataRecordUpload() {

Modified: jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptionsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptionsTest.java?rev=1872572&r1=1872571&r2=1872572&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptionsTest.java (original)
+++ jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptionsTest.java Fri Jan 10 04:38:45 2020
@@ -42,11 +42,11 @@ public class DataRecordDownloadOptionsTe
     private static final String DISPOSITION_TYPE_INLINE = "inline";
     private static final String DISPOSITION_TYPE_ATTACHMENT = "attachment";
 
-    private void verifyOptions(DataRecordDownloadOptions options,
-                               String mediaType,
-                               String characterEncoding,
-                               String fileName,
-                               String dispositionType) {
+    private void verifyDownloadOptions(DataRecordDownloadOptions options,
+                                       String mediaType,
+                                       String characterEncoding,
+                                       String fileName,
+                                       String dispositionType) {
         assertNotNull(options);
         if (null != mediaType) {
             assertEquals(mediaType, options.getMediaType());
@@ -146,7 +146,7 @@ public class DataRecordDownloadOptionsTe
         DataRecordDownloadOptions options =
                 DataRecordDownloadOptions.fromBlobDownloadOptions(blobDownloadOptions);
 
-        verifyOptions(options,
+        verifyDownloadOptions(options,
                 MEDIA_TYPE_TEXT_PLAIN,
                 CHARACTER_ENCODING_UTF_8,
                 FILE_NAME_TEXT,
@@ -155,12 +155,12 @@ public class DataRecordDownloadOptionsTe
 
     @Test
     public void testDefault() {
-        verifyOptions(DataRecordDownloadOptions.DEFAULT,
+        verifyDownloadOptions(DataRecordDownloadOptions.DEFAULT,
                 null,
                 null,
                 null,
                 DISPOSITION_TYPE_INLINE);
-        verifyOptions(DataRecordDownloadOptions
+        verifyDownloadOptions(DataRecordDownloadOptions
                 .fromBlobDownloadOptions(BlobDownloadOptions.DEFAULT),
                 null,
                 null,

Added: jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordUploadOptionsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordUploadOptionsTest.java?rev=1872572&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordUploadOptionsTest.java (added)
+++ jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordUploadOptionsTest.java Fri Jan 10 04:38:45 2020
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.apache.jackrabbit.oak.api.blob.BlobUploadOptions;
+import org.junit.Test;
+
+public class DataRecordUploadOptionsTest {
+    private void verifyUploadOptions(DataRecordUploadOptions options,
+                                     boolean expectedIsDomainOverrideIgnored) {
+        assertNotNull(options);
+        if (expectedIsDomainOverrideIgnored)
+            assertTrue(options.isDomainOverrideIgnored());
+        else
+            assertFalse(options.isDomainOverrideIgnored());
+    }
+
+    @Test
+    public void testConstruct() {
+        BlobUploadOptions blobOptions = new BlobUploadOptions(false);
+        DataRecordUploadOptions options = DataRecordUploadOptions.fromBlobUploadOptions(blobOptions);
+        verifyUploadOptions(options, false);
+    }
+
+    @Test
+    public void testDefault() {
+        verifyUploadOptions(DataRecordUploadOptions.DEFAULT, false);
+    }
+
+    @Test
+    public void testConstructFromNullThrowsException() {
+        try {
+            DataRecordUploadOptions.fromBlobUploadOptions(null);
+            fail("Exception expected but not thrown");
+        }
+        catch (NullPointerException | IllegalArgumentException e) { }
+    }
+
+    @Test
+    public void testIsDomainOverrideIgnored() {
+        verifyUploadOptions(
+                DataRecordUploadOptions.fromBlobUploadOptions(
+                        new BlobUploadOptions(true)
+                ),
+                true
+        );
+    }
+}

Modified: jackrabbit/oak/trunk/oak-doc/src/site/markdown/features/direct-binary-access.md
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-doc/src/site/markdown/features/direct-binary-access.md?rev=1872572&r1=1872571&r2=1872572&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-doc/src/site/markdown/features/direct-binary-access.md (original)
+++ jackrabbit/oak/trunk/oak-doc/src/site/markdown/features/direct-binary-access.md Fri Jan 10 04:38:45 2020
@@ -264,3 +264,18 @@ When set, the property value should be a
 CDNs may be used for direct upload as well as direct download, if the CDN in question supports such behavior.  CDNs that support this behavior include AWS CloudFront, all Azure CDN offerings, and some other third-party CDNs do as well; however, these capabilities are the responsibility of the service providers, not Oak.  Check with your CDN provider for authoritative information on suitability; comprehensive testing is recommended.
 
 Note that you are not required to configure both domains, nor is it required that both domains be the same.  For example, if one CDN offers the best download performance and another CDN offers the best upload performance, you may choose to implement both and set each configuration parameter to a different domain.  Likewise, you are not required to set them both.  If you only wish to use CDNs for download but not upload, simply configure the download parameter with the CDN domain and don't configure an upload domain.
+
+## Ignoring the Domain Override
+
+`@since Oak 1.22 (AzureDataStore)`
+
+Usually if a domain override is configured, this value should be used for all signed URI requests because using this domain should result in a better experience.  However, there can be cases where a client does not want to use the domain override even if it is configured.
+
+For example, suppose you have a service running in the cloud and this service will be issuing requests with signed URIs.  Suppose that this service is running in the same cloud region as your blob storage.  In such a case, it will probably be much faster for the service to resolve the URI request using the default URI domain rather than the CDN domain, because most cloud service providers resolve these DNS names internally and route the traffic much more efficiently.  If the client that asks for the signed URI knows that it will be giving the URI to such a service to download, it may wish to indicate that it wants to ignore any configured domain override for this URI.
+
+To specify this behavior for signed download URIs, the client requesting the URI should specify to ignore the domain override when building the `BinaryDownloadOptions`:
+
+```
+BinaryDownloadOptions.BinaryDownloadOptionsBuilder builder = BinaryDownloadOptions.builder()
+    .withDomainOverrideIgnored(true);
+```

Modified: jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/JackrabbitValueFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/JackrabbitValueFactory.java?rev=1872572&r1=1872571&r2=1872572&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/JackrabbitValueFactory.java (original)
+++ jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/JackrabbitValueFactory.java Fri Jan 10 04:38:45 2020
@@ -28,6 +28,7 @@ import javax.jcr.ValueFactory;
 import org.apache.jackrabbit.api.binary.BinaryDownloadOptions;
 import org.apache.jackrabbit.api.binary.BinaryUpload;
 import org.apache.jackrabbit.api.binary.BinaryDownload;
+import org.apache.jackrabbit.api.binary.BinaryUploadOptions;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.osgi.annotation.versioning.ProviderType;
@@ -92,7 +93,10 @@ import org.osgi.annotation.versioning.Pr
  *         <b>Initialize</b>: A remote client makes request to the
  *         Jackrabbit-based application to request an upload, which calls {@link
  *         #initiateBinaryUpload(long, int)} and returns the resulting {@link
- *         BinaryUpload instructions} to the remote client.
+ *         BinaryUpload instructions} to the remote client.  A client may
+ *         optionally choose to provide a {@link BinaryUploadOptions} via
+ *         {@link #initiateBinaryUpload(long, int, BinaryUploadOptions)} if
+ *         additional options must be specified.
  *     </li>
  *     <li>
  *         <b>Upload</b>: The remote client performs the actual binary upload
@@ -159,6 +163,50 @@ public interface JackrabbitValueFactory
             throws IllegalArgumentException, AccessDeniedException;
 
     /**
+     * Initiate a transaction to upload a binary directly to a storage
+     * location and return {@link BinaryUpload} instructions for a remote client.
+     * Returns {@code null} if the feature is not available.
+     *
+     * <p>
+     * {@link IllegalArgumentException} will be thrown if an upload
+     * cannot be supported for the required parameters, or if the parameters are
+     * otherwise invalid. Each service provider has specific limitations.
+     *
+     * @param maxSize The exact size of the binary to be uploaded or the
+     *                estimated maximum size if the exact size is unknown.
+     *                If the estimation was too small, the transaction
+     *                should be restarted by invoking this method again
+     *                using the correct size.
+     * @param maxURIs The maximum number of upload URIs that the client can
+     *                accept, for example due to message size limitations.
+     *                A value of -1 indicates no limit.
+     *                Upon a successful return, it is ensured that an upload
+     *                of {@code maxSize} can be completed by splitting the
+     *                binary into {@code maxURIs} parts, otherwise
+     *                {@link IllegalArgumentException} will be thrown.
+     * @param options A {@link BinaryUploadOptions} instance containing any
+     *                options for this call.
+     *
+     * @return A {@link BinaryUpload} providing the upload instructions,
+     *         or {@code null} if the implementation does not support the direct
+     *         upload feature.
+     *
+     * @throws IllegalArgumentException if the provided arguments are
+     *         invalid or if an upload cannot be completed given the
+     *         provided arguments. For example, if the value of {@code maxSize}
+     *         exceeds the size limits for a single binary upload for the
+     *         implementation or the service provider, or if the value of
+     *         {@code maxSize} divided by {@code maxParts} exceeds the size
+     *         limit for an upload or upload part.
+     *
+     * @throws AccessDeniedException if the session has insufficient
+     *         permission to perform the upload.
+     */
+    @Nullable
+    BinaryUpload initiateBinaryUpload(long maxSize, int maxURIs, BinaryUploadOptions options)
+            throws IllegalArgumentException, AccessDeniedException;
+
+    /**
      * Complete the transaction of uploading a binary directly to a storage
      * location and return a {@link Binary} to set as value for a binary
      * JCR property. The binary is not automatically associated with

Modified: jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/BinaryDownloadOptions.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/BinaryDownloadOptions.java?rev=1872572&r1=1872571&r2=1872572&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/BinaryDownloadOptions.java (original)
+++ jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/BinaryDownloadOptions.java Fri Jan 10 04:38:45 2020
@@ -41,15 +41,18 @@ public final class BinaryDownloadOptions
     private final String characterEncoding;
     private final String fileName;
     private final String dispositionType;
+    private boolean downloadDomainIgnored = false;
 
     private BinaryDownloadOptions(final String mediaType,
                                   final String characterEncoding,
                                   final String fileName,
-                                  final String dispositionType) {
+                                  final String dispositionType,
+                                  boolean downloadDomainIgnored) {
         this.mediaType = mediaType;
         this.characterEncoding = characterEncoding;
         this.fileName = fileName;
         this.dispositionType = dispositionType;
+        this.downloadDomainIgnored = downloadDomainIgnored;
     }
 
     /**
@@ -125,6 +128,17 @@ public final class BinaryDownloadOptions
     }
 
     /**
+     * Returns a boolean value that indicates whether the data store should
+     * ignore any provided download domain override configuration value when
+     * generating the signed URI.  This value can be set by calling {@link
+     * BinaryDownloadOptionsBuilder#withDomainOverrideIgnored(boolean)}.  The
+     * default value of this setting is false.
+     *
+     * @return true if the domain override should be ignored; false otherwise.
+     */
+    public boolean isDownloadDomainIgnored() { return downloadDomainIgnored; }
+
+    /**
      * Returns a {@link BinaryDownloadOptionsBuilder} instance to be used for
      * creating an instance of this class.
      *
@@ -144,6 +158,7 @@ public final class BinaryDownloadOptions
         private String characterEncoding = null;
         private String fileName = null;
         private DispositionType dispositionType = DispositionType.INLINE;
+        private boolean domainOverrideIgnored = false;
 
         private BinaryDownloadOptionsBuilder() { }
 
@@ -283,6 +298,36 @@ public final class BinaryDownloadOptions
         }
 
         /**
+         * Sets a flag to indicate whether any configured download domain
+         * override value should be ignored when generating the signed download
+         * URI.
+         * <p>
+         *
+         * The default value of this flag is false.  This means that if a
+         * download domain override configuration value is provided, that value
+         * will be used in a signed download URI as the hostname, and if not
+         * provided the default hostname will be used instead.  However, if this
+         * flag is set to true, the implementation will use the default hostname
+         * for the signed download URI regardless of whether the download domain
+         * override value is configured or not.
+         *
+         * Most clients will want to accept the default behavior.  However, if a
+         * client understands its deployment topology it may know that ignoring
+         * the download domain override will provide better performance.  An
+         * example of this is if the client is a service running in the same
+         * cloud region as the blob store, in which case accessing the storage
+         * directly is almost always faster than going through a domain override
+         * (e.g. CDN domain).
+         *
+         * @param domainOverrideIgnored
+         * @return The calling instance.
+         */
+        public BinaryDownloadOptionsBuilder withDomainOverrideIgnored(boolean domainOverrideIgnored) {
+            this.domainOverrideIgnored = domainOverrideIgnored;
+            return this;
+        }
+
+        /**
          * Construct a {@link BinaryDownloadOptions} instance with the
          * properties specified to the builder.
          *
@@ -296,7 +341,8 @@ public final class BinaryDownloadOptions
                     fileName,
                     null != dispositionType
                             ? dispositionType.toString()
-                            : DispositionType.INLINE.toString()
+                            : DispositionType.INLINE.toString(),
+                    domainOverrideIgnored
             );
         }
 

Added: jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/BinaryUploadOptions.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/BinaryUploadOptions.java?rev=1872572&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/BinaryUploadOptions.java (added)
+++ jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/BinaryUploadOptions.java Fri Jan 10 04:38:45 2020
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.jackrabbit.api.binary;
+
+import org.jetbrains.annotations.NotNull;
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * Specifies the options to be used when requesting direct upload URIs via
+ * {@link org.apache.jackrabbit.api.JackrabbitValueFactory#initiateBinaryUpload(long, int, BinaryUploadOptions)}.
+ * <p>
+ * To specify upload options, obtain a {@link BinaryUploadOptionsBuilder}
+ * via the {@link #builder()} method, then specify the options desired and
+ * get the object via {@link BinaryUploadOptionsBuilder#build()}.
+ * <p>
+ * If no options are needed, use {@link BinaryUploadOptions#DEFAULT} which
+ * instructs the implementation to use the service provider default behavior.
+ */
+@ProviderType
+public final class BinaryUploadOptions {
+    private final boolean domainOverrideIgnore;
+
+    private BinaryUploadOptions(boolean domainOverrideIgnore) {
+        this.domainOverrideIgnore = domainOverrideIgnore;
+    }
+
+    /**
+     * Provides a default instance of this class.  This instance enforces the
+     * proper default behaviors for the options.
+     */
+    public static final BinaryUploadOptions DEFAULT =
+            BinaryUploadOptions.builder().build();
+
+    /**
+     * Indicates whether the option to ignore any configured domain override
+     * setting has been specified.
+     *
+     * @return true if the domain override should be ignored; false otherwise.
+     * The default behavior is {@code false}, meaning that any configured domain
+     * override setting should be honored.
+     */
+    public boolean isDomainOverrideIgnored() {
+        return domainOverrideIgnore;
+    }
+
+    /**
+     * Returns a {@link BinaryUploadOptionsBuilder} instance to be used for
+     * creating an instance of this class.
+     *
+     * @return A builder instance.
+     */
+    @NotNull
+    public static BinaryUploadOptionsBuilder builder() {
+        return new BinaryUploadOptionsBuilder();
+    }
+
+    /**
+     * Used to build an instance of {@link BinaryUploadOptions} with the options
+     * set as desired by the caller.
+     */
+    public static final class BinaryUploadOptionsBuilder {
+        private boolean domainOverrideIgnore = false;
+
+        private BinaryUploadOptionsBuilder() { }
+
+        /**
+         * Sets the option to ignore any configured domain override setting.
+         *
+         * The default value of this option is false, meaning that any
+         * configured domain override setting should be honored when generating
+         * signed upload URIs.  Setting this value to true will indicate that
+         * the signed upload URIs being generated should not honor any
+         * configured domain override setting.
+         *
+         * @param domainOverrideIgnore true to ignore any configured domain
+         *                             override setting, false otherwise.
+         * @return the calling instance.
+         */
+        public BinaryUploadOptionsBuilder withDomainOverrideIgnore(boolean domainOverrideIgnore) {
+            this.domainOverrideIgnore = domainOverrideIgnore;
+            return this;
+        }
+
+        /**
+         * Construct a {@link BinaryUploadOptions} instance with the
+         * properties specified to the builder.
+         *
+         * @return A new {@link BinaryUploadOptions} instance built with the
+         *         properties specified to the builder.
+         */
+        public BinaryUploadOptions build() {
+            return new BinaryUploadOptions(domainOverrideIgnore);
+        }
+    }
+}

Modified: jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/package-info.java?rev=1872572&r1=1872571&r2=1872572&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/package-info.java (original)
+++ jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/package-info.java Fri Jan 10 04:38:45 2020
@@ -20,7 +20,7 @@
 /**
  * Interfaces related to direct upload/download of binaries.
  */
-@Version("1.0.0")
+@Version("1.1.0")
 package org.apache.jackrabbit.api.binary;
 
 import org.osgi.annotation.versioning.Version;
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/package-info.java?rev=1872572&r1=1872571&r2=1872572&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/package-info.java (original)
+++ jackrabbit/oak/trunk/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/package-info.java Fri Jan 10 04:38:45 2020
@@ -18,5 +18,5 @@
 /**
  * Jackrabbit extensions for JCR core interfaces
  */
-@org.osgi.annotation.versioning.Version("2.5.0")
+@org.osgi.annotation.versioning.Version("2.6.0")
 package org.apache.jackrabbit.api;

Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/BinaryAccessTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/BinaryAccessTest.java?rev=1872572&r1=1872571&r2=1872572&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/BinaryAccessTest.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/BinaryAccessTest.java Fri Jan 10 04:38:45 2020
@@ -51,6 +51,7 @@ import org.apache.jackrabbit.oak.api.Blo
 import org.apache.jackrabbit.oak.api.blob.BlobAccessProvider;
 import org.apache.jackrabbit.oak.api.blob.BlobDownloadOptions;
 import org.apache.jackrabbit.oak.api.blob.BlobUpload;
+import org.apache.jackrabbit.oak.api.blob.BlobUploadOptions;
 import org.apache.jackrabbit.oak.fixture.NodeStoreFixture;
 import org.apache.jackrabbit.oak.jcr.AbstractRepositoryTest;
 import org.apache.jackrabbit.oak.jcr.Jcr;
@@ -135,6 +136,12 @@ public class BinaryAccessTest extends Ab
 
         @Override
         public @Nullable BlobUpload initiateBlobUpload(long maxSize, int maxURIs) throws IllegalArgumentException {
+            return initiateBlobUpload(maxSize, maxURIs, BlobUploadOptions.DEFAULT);
+        }
+
+        @Override
+        public @Nullable BlobUpload initiateBlobUpload(long maxSize, int maxURIs, @NotNull final BlobUploadOptions options)
+                throws IllegalArgumentException {
             return new BlobUpload() {
                 @Override
                 public @NotNull String getUploadToken() {

Modified: jackrabbit/oak/trunk/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/plugins/value/jcr/PartialValueFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/plugins/value/jcr/PartialValueFactory.java?rev=1872572&r1=1872571&r2=1872572&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/plugins/value/jcr/PartialValueFactory.java (original)
+++ jackrabbit/oak/trunk/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/plugins/value/jcr/PartialValueFactory.java Fri Jan 10 04:38:45 2020
@@ -39,6 +39,7 @@ import org.apache.jackrabbit.oak.api.Pro
 import org.apache.jackrabbit.oak.api.blob.BlobAccessProvider;
 import org.apache.jackrabbit.oak.api.blob.BlobDownloadOptions;
 import org.apache.jackrabbit.oak.api.blob.BlobUpload;
+import org.apache.jackrabbit.oak.api.blob.BlobUploadOptions;
 import org.apache.jackrabbit.oak.commons.UUIDUtils;
 import org.apache.jackrabbit.oak.namepath.JcrNameParser;
 import org.apache.jackrabbit.oak.namepath.JcrPathParser;
@@ -265,6 +266,13 @@ public class PartialValueFactory {
         @Override
         public BlobUpload initiateBlobUpload(long maxUploadSizeInBytes,
                                              int maxNumberOfURIs) {
+            return initiateBlobUpload(maxUploadSizeInBytes, maxNumberOfURIs, BlobUploadOptions.DEFAULT);
+        }
+
+        @Nullable
+        public BlobUpload initiateBlobUpload(long maxUploadSizeInBytes,
+                                             int maxNumberOfURIs,
+                                             @NotNull final BlobUploadOptions options) {
             return null;
         }
 

Modified: jackrabbit/oak/trunk/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/plugins/value/jcr/ValueFactoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/plugins/value/jcr/ValueFactoryImpl.java?rev=1872572&r1=1872571&r2=1872572&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/plugins/value/jcr/ValueFactoryImpl.java (original)
+++ jackrabbit/oak/trunk/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/plugins/value/jcr/ValueFactoryImpl.java Fri Jan 10 04:38:45 2020
@@ -32,10 +32,12 @@ import javax.jcr.ValueFormatException;
 import org.apache.jackrabbit.api.JackrabbitValueFactory;
 import org.apache.jackrabbit.api.ReferenceBinary;
 import org.apache.jackrabbit.api.binary.BinaryUpload;
+import org.apache.jackrabbit.api.binary.BinaryUploadOptions;
 import org.apache.jackrabbit.oak.api.Blob;
 import org.apache.jackrabbit.oak.api.Root;
 import org.apache.jackrabbit.oak.api.blob.BlobAccessProvider;
 import org.apache.jackrabbit.oak.api.blob.BlobUpload;
+import org.apache.jackrabbit.oak.api.blob.BlobUploadOptions;
 import org.apache.jackrabbit.oak.commons.PerfLogger;
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 import org.apache.jackrabbit.oak.plugins.memory.BinaryPropertyState;
@@ -136,7 +138,16 @@ public class ValueFactoryImpl extends Pa
     @Override
     @Nullable
     public BinaryUpload initiateBinaryUpload(long maxSize, int maxParts) {
-        BlobUpload upload = getBlobAccessProvider().initiateBlobUpload(maxSize, maxParts);
+        return initiateBinaryUpload(maxSize, maxParts, BinaryUploadOptions.DEFAULT);
+    }
+
+    @Override
+    @Nullable
+    public BinaryUpload initiateBinaryUpload(long maxSize, int maxParts, @NotNull final BinaryUploadOptions options) {
+        BlobUpload upload = getBlobAccessProvider()
+                .initiateBlobUpload(maxSize,
+                        maxParts,
+                        new BlobUploadOptions(options.isDomainOverrideIgnored()));
         if (null == upload) {
             return null;
         }