diff --git a/data-model/src/main/java/org/alfresco/repo/content/ContentStore.java b/data-model/src/main/java/org/alfresco/repo/content/ContentStore.java
index ccded57adb..4344a15c87 100644
--- a/data-model/src/main/java/org/alfresco/repo/content/ContentStore.java
+++ b/data-model/src/main/java/org/alfresco/repo/content/ContentStore.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Data model classes
* %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -25,6 +25,8 @@
*/
package org.alfresco.repo.content;
+import java.util.Date;
+
import org.alfresco.api.AlfrescoPublicApi;
import org.alfresco.service.cmr.repository.ContentAccessor;
import org.alfresco.service.cmr.repository.ContentIOException;
@@ -32,8 +34,8 @@ import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentStreamListener;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.DirectAccessUrl;
+import org.alfresco.service.cmr.repository.NodeRef;
-import java.util.Date;
/**
* Provides low-level retrieval of content
@@ -239,6 +241,58 @@ public interface ContentStore
*/
public boolean delete(String contentUrl);
+ /**
+ * Checks if the store supports the retrieving of direct access URLs.
+ *
+ * @return {@code true} if direct access URLs retrieving is supported, {@code false} otherwise
+ */
+ default boolean isContentDirectUrlEnabled()
+ {
+ return false;
+ }
+
+ /**
+ * Checks if the store supports the retrieving of a direct access URL for the given node.
+ *
+ * @return {@code true} if direct access URLs retrieving is supported for the node, {@code false} otherwise
+ */
+ default boolean isContentDirectUrlEnabled(NodeRef nodeRef)
+ {
+ return false;
+ }
+
+ /**
+ * Gets a presigned URL to directly access the content. It is up to the actual store
+ * implementation if it can fulfil this request with an expiry time or not.
+ *
+ * @param contentUrl A content store {@code URL}
+ * @param attachment {@code true} if an attachment URL is requested, {@code false} for an embedded {@code URL}.
+ * @param fileName File name of the content
+ * @return A direct access {@code URL} object for the content
+ * @throws UnsupportedOperationException if the store is unable to provide the information
+ */
+ default DirectAccessUrl requestContentDirectUrl(String contentUrl, boolean attachment, String fileName)
+ {
+ return requestContentDirectUrl(contentUrl, attachment, fileName, null);
+ }
+
+ /**
+ * Gets a presigned URL to directly access the content. It is up to the actual store
+ * implementation if it can fulfil this request with an expiry time or not.
+ *
+ * @param contentUrl A content store {@code URL}
+ * @param attachment {@code true} if an attachment URL is requested, {@code false} for an embedded {@code URL}.
+ * @param fileName File name of the content
+ * @param validFor The time at which the direct access {@code URL} will expire.
+ * @return A direct access {@code URL} object for the content.
+ * @throws UnsupportedOperationException if the store is unable to provide the information
+ */
+ default DirectAccessUrl requestContentDirectUrl(String contentUrl, boolean attachment, String fileName, Long validFor)
+ {
+ throw new UnsupportedOperationException(
+ "Retrieving direct access URLs is not supported by this content store.");
+ }
+
/**
* Gets a presigned URL to directly access a binary content. It is up to the actual store
* implementation if it can fulfil this request with an expiry time or not.
@@ -248,10 +302,11 @@ public interface ContentStore
* @return A direct access URL object for a binary content
* @throws UnsupportedOperationException if the store is unable to provide the information
*/
+ @Deprecated
default DirectAccessUrl getDirectAccessUrl(String contentUrl, Date expiresAt)
{
throw new UnsupportedOperationException(
- "Retrieving direct access URLs is not supported by this content store.");
+ "Retrieving direct access URLs is not supported by this content store.");
}
/**
@@ -259,6 +314,7 @@ public interface ContentStore
*
* @return true if direct access URLs retrieving is supported, false otherwise
*/
+ @Deprecated
default boolean isDirectAccessSupported()
{
return false;
diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/DirectAccessUrl.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/DirectAccessUrl.java
index 0df9532f7a..365f441bb2 100644
--- a/data-model/src/main/java/org/alfresco/service/cmr/repository/DirectAccessUrl.java
+++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/DirectAccessUrl.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Data model classes
* %%
- * Copyright (C) 2005 - 2020 Alfresco Software Limited
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -27,6 +27,7 @@ package org.alfresco.service.cmr.repository;
import java.io.Serializable;
import java.util.Date;
+import java.util.Objects;
import org.alfresco.api.AlfrescoPublicApi;
@@ -36,7 +37,8 @@ public class DirectAccessUrl implements Serializable
private static final long serialVersionUID = -881676208224414139L;
private String contentUrl;
- private Date expiresAt;
+ private Date expiryTime;
+ private boolean attachment;
public String getContentUrl()
{
@@ -48,13 +50,38 @@ public class DirectAccessUrl implements Serializable
this.contentUrl = contentUrl;
}
- public Date getExpiresAt()
+ public Date getExpiryTime()
{
- return expiresAt;
+ return expiryTime;
}
- public void setExpiresAt(Date expiresAt)
+ public void setExpiryTime(Date expiryTime)
{
- this.expiresAt = expiresAt;
+ this.expiryTime = expiryTime;
+ }
+
+ public boolean isAttachment()
+ {
+ return attachment;
+ }
+
+ public void setAttachment(boolean attachment)
+ {
+ this.attachment = attachment;
+ }
+
+ @Override public boolean equals(Object obj)
+ {
+ if (this == obj) return true;
+ if (obj == null || getClass() != obj.getClass()) return false;
+
+ DirectAccessUrl that = (DirectAccessUrl) obj;
+ return attachment == that.attachment && Objects.equals(contentUrl,
+ that.contentUrl) && Objects.equals(expiryTime, that.expiryTime);
+ }
+
+ @Override public int hashCode()
+ {
+ return Objects.hash(contentUrl, expiryTime, attachment);
}
}
diff --git a/repository/src/main/java/org/alfresco/repo/content/ContentServiceImpl.java b/repository/src/main/java/org/alfresco/repo/content/ContentServiceImpl.java
index 86e58e6527..158306bed0 100644
--- a/repository/src/main/java/org/alfresco/repo/content/ContentServiceImpl.java
+++ b/repository/src/main/java/org/alfresco/repo/content/ContentServiceImpl.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2019 Alfresco Software Limited
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -25,12 +25,21 @@
*/
package org.alfresco.repo.content;
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.ContentServicePolicies.OnContentPropertyUpdatePolicy;
import org.alfresco.repo.content.ContentServicePolicies.OnContentReadPolicy;
import org.alfresco.repo.content.ContentServicePolicies.OnContentUpdatePolicy;
import org.alfresco.repo.content.cleanup.EagerContentStoreCleaner;
+import org.alfresco.repo.content.directurl.DirectAccessUrlDisabledException;
+import org.alfresco.repo.content.directurl.SystemWideDirectUrlConfig;
import org.alfresco.repo.content.filestore.FileContentStore;
import org.alfresco.repo.node.NodeServicePolicies;
import org.alfresco.repo.policy.ClassPolicyDelegate;
@@ -47,6 +56,7 @@ import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.DirectAccessUrl;
+import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.service.cmr.repository.MimetypeServiceAware;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -62,13 +72,6 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.extensions.surf.util.I18NUtil;
-import java.io.Serializable;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
/**
* Service implementation acting as a level of indirection between the client
* and the underlying content store.
@@ -82,7 +85,7 @@ import java.util.Set;
*/
public class ContentServiceImpl implements ContentService, ApplicationContextAware
{
- private static Log logger = LogFactory.getLog(ContentServiceImpl.class);
+ private static final Log logger = LogFactory.getLog(ContentServiceImpl.class);
private DictionaryService dictionaryService;
private NodeService nodeService;
@@ -99,6 +102,8 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa
/** Should we consider zero byte content to be the same as no content? */
private boolean ignoreEmptyContent;
+ private SystemWideDirectUrlConfig systemWideDirectUrlConfig;
+
/**
* The policy component
*/
@@ -140,7 +145,12 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa
{
this.store = store;
}
-
+
+ public void setSystemWideDirectUrlConfig(SystemWideDirectUrlConfig systemWideDirectUrlConfig)
+ {
+ this.systemWideDirectUrlConfig = systemWideDirectUrlConfig;
+ }
+
public void setPolicyComponent(PolicyComponent policyComponent)
{
this.policyComponent = policyComponent;
@@ -510,23 +520,10 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa
return tempStore.getWriter(ContentContext.NULL_CONTEXT);
}
- @Override
+ @Deprecated
public DirectAccessUrl getDirectAccessUrl(NodeRef nodeRef, Date expiresAt)
{
- ContentData contentData = getContentData(nodeRef, ContentModel.PROP_CONTENT);
-
- // check that the URL is available
- if (contentData == null || contentData.getContentUrl() == null)
- {
- throw new IllegalArgumentException("The supplied nodeRef " + nodeRef + " has no content.");
- }
-
- if (store.isDirectAccessSupported())
- {
- return store.getDirectAccessUrl(contentData.getContentUrl(), expiresAt);
- }
-
- return null;
+ return requestContentDirectUrl(nodeRef, true, null);
}
/**
@@ -586,4 +583,104 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa
}
}
}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isContentDirectUrlEnabled()
+ {
+ return systemWideDirectUrlConfig.isEnabled() && store.isContentDirectUrlEnabled();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isContentDirectUrlEnabled(NodeRef nodeRef)
+ {
+ boolean contentDirectUrlEnabled = false;
+
+ // TODO: update this
+ if (systemWideDirectUrlConfig.isEnabled())
+ {
+ ContentData contentData = getContentData(nodeRef, ContentModel.PROP_CONTENT);
+
+ // check that the URL is available
+ if (contentData == null || contentData.getContentUrl() == null)
+ {
+ throw new IllegalArgumentException("The supplied nodeRef " + nodeRef + " has no content.");
+ }
+
+ contentDirectUrlEnabled = (store.isContentDirectUrlEnabled(nodeRef));
+ }
+
+ return contentDirectUrlEnabled;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DirectAccessUrl requestContentDirectUrl(NodeRef nodeRef, boolean attachment, Long validFor)
+ {
+ if (!systemWideDirectUrlConfig.isEnabled())
+ {
+ throw new DirectAccessUrlDisabledException("Direct access url isn't available.");
+ }
+
+ String contentUrl = getContentUrl(nodeRef);
+ String fileName = getFileName(nodeRef);
+ validFor = adjustValidFor(validFor);
+
+ DirectAccessUrl directAccessUrl = null;
+ if (store.isContentDirectUrlEnabled())
+ {
+ try
+ {
+ directAccessUrl = store.requestContentDirectUrl(contentUrl, attachment, fileName, validFor);
+ }
+ catch (UnsupportedOperationException ex)
+ {
+ // expected exception
+ }
+ }
+ return directAccessUrl;
+ }
+
+ protected String getContentUrl(NodeRef nodeRef)
+ {
+ ContentData contentData = getContentData(nodeRef, ContentModel.PROP_CONTENT);
+
+ // check that the URL is available
+ if (contentData == null || contentData.getContentUrl() == null)
+ {
+ throw new IllegalArgumentException("The supplied nodeRef " + nodeRef + " has no content.");
+ }
+
+ return contentData.getContentUrl();
+ }
+
+ protected String getFileName(NodeRef nodeRef)
+ {
+ String fileName = null;
+
+ try
+ {
+ fileName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
+ }
+ catch (InvalidNodeRefException ex)
+ {
+ }
+
+ return fileName;
+ }
+
+ private Long adjustValidFor(Long validFor)
+ {
+ if (validFor == null || validFor > systemWideDirectUrlConfig.getDefaultExpiryTimeInSec())
+ {
+ validFor = systemWideDirectUrlConfig.getDefaultExpiryTimeInSec();
+ }
+ return validFor;
+ }
}
\ No newline at end of file
diff --git a/repository/src/main/java/org/alfresco/repo/content/caching/CachingContentStore.java b/repository/src/main/java/org/alfresco/repo/content/caching/CachingContentStore.java
index 5cad001984..77e7851547 100644
--- a/repository/src/main/java/org/alfresco/repo/content/caching/CachingContentStore.java
+++ b/repository/src/main/java/org/alfresco/repo/content/caching/CachingContentStore.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -25,7 +25,6 @@
*/
package org.alfresco.repo.content.caching;
-import java.util.Date;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
@@ -41,6 +40,7 @@ import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentStreamListener;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.DirectAccessUrl;
+import org.alfresco.service.cmr.repository.NodeRef;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanNameAware;
@@ -103,7 +103,7 @@ public class CachingContentStore implements ContentStore, ApplicationEventPublis
{
eventPublisher.publishEvent(new CachingContentStoreCreatedEvent(this));
}
-
+
@Override
public boolean isContentUrlSupported(String contentUrl)
{
@@ -137,7 +137,7 @@ public class CachingContentStore implements ContentStore, ApplicationEventPublis
/**
* {@inheritDoc}
*
- * For {@link #SPOOF_PROTOCOL spoofed} URLs, the URL always exists.
+ * For {@link FileContentStore#SPOOF_PROTOCOL spoofed} URLs, the URL always exists.
*/
@Override
public boolean exists(String contentUrl)
@@ -478,13 +478,35 @@ public class CachingContentStore implements ContentStore, ApplicationEventPublis
return this.beanName;
}
- public boolean isDirectAccessSupported()
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isContentDirectUrlEnabled()
{
- return backingStore.isDirectAccessSupported();
+ return backingStore.isContentDirectUrlEnabled();
}
- public DirectAccessUrl getDirectAccessUrl(String contentUrl, Date expiresAt)
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isContentDirectUrlEnabled(NodeRef nodeRef)
{
- return backingStore.getDirectAccessUrl(contentUrl, expiresAt);
+ return backingStore.isContentDirectUrlEnabled(nodeRef);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DirectAccessUrl requestContentDirectUrl(String contentUrl, boolean attachment, String fileName)
+ {
+ return backingStore.requestContentDirectUrl(contentUrl, attachment, fileName);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DirectAccessUrl requestContentDirectUrl(String contentUrl, boolean attachment, String fileName, Long validFor)
+ {
+ return backingStore.requestContentDirectUrl(contentUrl, attachment, fileName, validFor);
}
}
diff --git a/repository/src/main/java/org/alfresco/repo/content/directurl/DirectAccessUrlDisabledException.java b/repository/src/main/java/org/alfresco/repo/content/directurl/DirectAccessUrlDisabledException.java
new file mode 100644
index 0000000000..d0702b398d
--- /dev/null
+++ b/repository/src/main/java/org/alfresco/repo/content/directurl/DirectAccessUrlDisabledException.java
@@ -0,0 +1,44 @@
+/*
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.repo.content.directurl;
+
+import org.alfresco.error.AlfrescoRuntimeException;
+
+/**
+ * Runtime exception thrown when direct access URLs are disabled.
+ *
+ * @author Sara Aspery
+ */
+public class DirectAccessUrlDisabledException extends AlfrescoRuntimeException
+{
+
+ private static final long serialVersionUID = -6506082117146782993L;
+
+ public DirectAccessUrlDisabledException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/repository/src/main/java/org/alfresco/repo/content/replication/AggregatingContentStore.java b/repository/src/main/java/org/alfresco/repo/content/replication/AggregatingContentStore.java
index 15cc9c5246..6c700e0572 100644
--- a/repository/src/main/java/org/alfresco/repo/content/replication/AggregatingContentStore.java
+++ b/repository/src/main/java/org/alfresco/repo/content/replication/AggregatingContentStore.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -25,7 +25,6 @@
*/
package org.alfresco.repo.content.replication;
-import java.util.Date;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
@@ -41,6 +40,7 @@ import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.DirectAccessUrl;
+import org.alfresco.service.cmr.repository.NodeRef;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -65,7 +65,7 @@ import org.apache.commons.logging.LogFactory;
*/
public class AggregatingContentStore extends AbstractContentStore
{
- private static Log logger = LogFactory.getLog(AggregatingContentStore.class);
+ private static final Log logger = LogFactory.getLog(AggregatingContentStore.class);
private ContentStore primaryStore;
private List secondaryStores;
@@ -266,33 +266,58 @@ public class AggregatingContentStore extends AbstractContentStore
}
/**
- * @return Returns true if at least one store supports direct access
+ * @return Returns {@code true} if at least one store supports direct access URLs
*/
- public boolean isDirectAccessSupported()
+ public boolean isContentDirectUrlEnabled()
{
// Check the primary store
- boolean isDirectAccessSupported = primaryStore.isDirectAccessSupported();
+ boolean isContentDirectUrlEnabled = primaryStore.isContentDirectUrlEnabled();
- if (!isDirectAccessSupported)
+ if (!isContentDirectUrlEnabled)
{
// Direct access is not supported by the primary store so we have to check the
// other stores
for (ContentStore store : secondaryStores)
{
+ isContentDirectUrlEnabled = store.isContentDirectUrlEnabled();
- isDirectAccessSupported = store.isDirectAccessSupported();
-
- if (isDirectAccessSupported)
+ if (isContentDirectUrlEnabled)
{
break;
}
}
}
- return isDirectAccessSupported;
+ return isContentDirectUrlEnabled;
}
- public DirectAccessUrl getDirectAccessUrl(String contentUrl, Date expiresAt)
+ /**
+ * @return Returns {@code true} if at least one store supports direct access URL for node
+ */
+ public boolean isContentDirectUrlEnabled(NodeRef nodeRef)
+ {
+ // Check the primary store
+ boolean isContentDirectUrlEnabled = primaryStore.isContentDirectUrlEnabled(nodeRef);
+
+ if (!isContentDirectUrlEnabled)
+ {
+ // Direct access is not supported by the primary store so we have to check the
+ // other stores
+ for (ContentStore store : secondaryStores)
+ {
+ isContentDirectUrlEnabled = store.isContentDirectUrlEnabled(nodeRef);
+
+ if (isContentDirectUrlEnabled)
+ {
+ break;
+ }
+ }
+ }
+
+ return isContentDirectUrlEnabled;
+ }
+
+ public DirectAccessUrl requestContentDirectUrl(String contentUrl, boolean attachment, String fileName, Long validFor)
{
if (primaryStore == null)
{
@@ -312,13 +337,13 @@ public class AggregatingContentStore extends AbstractContentStore
// Check the primary store
try
{
- directAccessUrl = primaryStore.getDirectAccessUrl(contentUrl, expiresAt);
+ directAccessUrl = primaryStore.requestContentDirectUrl(contentUrl, attachment, fileName, validFor);
}
catch (UnsupportedOperationException e)
{
// The store does not support direct access URL
directAccessUrlSupported = false;
- }
+ }
catch (UnsupportedContentUrlException e)
{
// The store can't handle the content URL
@@ -335,7 +360,7 @@ public class AggregatingContentStore extends AbstractContentStore
{
try
{
- directAccessUrl = store.getDirectAccessUrl(contentUrl, expiresAt);
+ directAccessUrl = store.requestContentDirectUrl(contentUrl, attachment, fileName, validFor);
}
catch (UnsupportedOperationException e)
{
diff --git a/repository/src/main/java/org/alfresco/service/cmr/repository/ContentService.java b/repository/src/main/java/org/alfresco/service/cmr/repository/ContentService.java
index 81622ff41a..ce73035374 100644
--- a/repository/src/main/java/org/alfresco/service/cmr/repository/ContentService.java
+++ b/repository/src/main/java/org/alfresco/service/cmr/repository/ContentService.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2019 Alfresco Software Limited
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -25,13 +25,13 @@
*/
package org.alfresco.service.cmr.repository;
+import java.util.Date;
+
import org.alfresco.api.AlfrescoPublicApi;
import org.alfresco.service.Auditable;
import org.alfresco.service.cmr.dictionary.InvalidTypeException;
import org.alfresco.service.namespace.QName;
-import java.util.Date;
-
/**
* Provides methods for accessing and transforming content.
*
@@ -168,6 +168,48 @@ public interface ContentService
* @return A direct access URL object for a binary content or returns null if not supported
* @throws IllegalArgumentException if there is no binary content for the node
*/
+ @Deprecated
@Auditable(parameters = {"nodeRef", "expiresAt"})
public DirectAccessUrl getDirectAccessUrl(NodeRef nodeRef, Date expiresAt);
+
+ /**
+ * Checks if the system and at least one store supports the retrieving of direct access URLs.
+ *
+ * @return {@code true} if direct access URLs retrieving is supported, {@code false} otherwise
+ */
+ boolean isContentDirectUrlEnabled();
+
+ /**
+ * Checks if the system and store supports the retrieving of a direct access {@code URL} for the given node.
+ *
+ * @return {@code true} if direct access URLs retrieving is supported for the node, {@code false} otherwise
+ */
+ boolean isContentDirectUrlEnabled(NodeRef nodeRef);
+
+ /**
+ * Gets a presigned URL to directly access the content. It is up to the actual store
+ * implementation if it can fulfil this request with an expiry time or not.
+ *
+ * @param nodeRef Node ref for which to obtain the direct access {@code URL}.
+ * @param attachment {@code true} if an attachment URL is requested, {@code false} for an embedded {@code URL}.
+ * @return A direct access {@code URL} object for the content.
+ * @throws UnsupportedOperationException if the store is unable to provide the information.
+ */
+ default DirectAccessUrl requestContentDirectUrl(NodeRef nodeRef, boolean attachment)
+ {
+ return requestContentDirectUrl(nodeRef, attachment, null);
+ }
+
+ /**
+ * Gets a presigned URL to directly access the content. It is up to the actual store
+ * implementation if it can fulfil this request with an expiry time or not.
+ *
+ * @param nodeRef Node ref for which to obtain the direct access {@code URL}.
+ * @param attachment {@code true} if an attachment URL is requested, {@code false} for an embedded {@code URL}.
+ * @param validFor The time at which the direct access {@code URL} will expire.
+ * @return A direct access {@code URL} object for the content.
+ * @throws UnsupportedOperationException if the store is unable to provide the information.
+ */
+ @Auditable(parameters = {"nodeRef", "validFor"})
+ DirectAccessUrl requestContentDirectUrl(NodeRef nodeRef, boolean attachment, Long validFor);
}
diff --git a/repository/src/main/resources/alfresco/content-services-context.xml b/repository/src/main/resources/alfresco/content-services-context.xml
index ab02159381..a086db2e41 100644
--- a/repository/src/main/resources/alfresco/content-services-context.xml
+++ b/repository/src/main/resources/alfresco/content-services-context.xml
@@ -161,6 +161,9 @@
${policy.content.update.ignoreEmpty}
+
+
+
diff --git a/repository/src/main/resources/alfresco/repository.properties b/repository/src/main/resources/alfresco/repository.properties
index 4979b06b90..b95cbf72ae 100644
--- a/repository/src/main/resources/alfresco/repository.properties
+++ b/repository/src/main/resources/alfresco/repository.properties
@@ -1291,7 +1291,7 @@ connector.s3.directAccessUrl.maxExpiryTimeInSec=300
# Configure the REST API configuration settings for direct access urls.
#
# Controls whether direct access url requests via the REST API are enabled.
-restApi.directAccessUrl.enabled=true
+restApi.directAccessUrl.enabled=false
# Sets the expiry time for all the direct access urls requested via a REST call.
# Its value cannot exceed the system-wide max expiry time configuration, it can only be equal or lower (REST API DAUs
# disabled otherwise).
diff --git a/repository/src/test/java/org/alfresco/AllUnitTestsSuite.java b/repository/src/test/java/org/alfresco/AllUnitTestsSuite.java
index 2d8cc48e74..7836b7cbec 100644
--- a/repository/src/test/java/org/alfresco/AllUnitTestsSuite.java
+++ b/repository/src/test/java/org/alfresco/AllUnitTestsSuite.java
@@ -180,6 +180,7 @@ import org.junit.runners.Suite;
org.alfresco.repo.audit.AuditableAnnotationTest.class,
org.alfresco.repo.audit.PropertyAuditFilterTest.class,
org.alfresco.repo.audit.access.NodeChangeTest.class,
+ org.alfresco.repo.content.ContentServiceImplUnitTest.class,
org.alfresco.repo.content.directurl.SystemWideDirectUrlConfigUnitTest.class,
org.alfresco.repo.content.directurl.ContentStoreDirectUrlConfigUnitTest.class,
org.alfresco.repo.content.LimitedStreamCopierTest.class,
diff --git a/repository/src/test/java/org/alfresco/repo/content/ContentServiceImplUnitTest.java b/repository/src/test/java/org/alfresco/repo/content/ContentServiceImplUnitTest.java
new file mode 100644
index 0000000000..63e6530715
--- /dev/null
+++ b/repository/src/test/java/org/alfresco/repo/content/ContentServiceImplUnitTest.java
@@ -0,0 +1,160 @@
+/*
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.repo.content;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.openMocks;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.content.directurl.DirectAccessUrlDisabledException;
+import org.alfresco.repo.content.directurl.SystemWideDirectUrlConfig;
+import org.alfresco.service.cmr.repository.ContentData;
+import org.alfresco.service.cmr.repository.DirectAccessUrl;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+/**
+ * Unit tests for content service implementation.
+ *
+ * @author Sara Aspery
+ */
+public class ContentServiceImplUnitTest
+{
+ private static final Boolean ENABLED = Boolean.TRUE;
+ private static final Boolean DISABLED = Boolean.FALSE;
+
+ private static final Long SYS_DEFAULT_EXPIRY_TIME_IN_SECS = 30L;
+ private static final Long SYS_MAX_EXPIRY_TIME_IN_SECS = 300L;
+
+ private static final NodeRef NODE_REF = new NodeRef("content://Node/Ref");
+
+ @InjectMocks
+ private ContentServiceImpl contentService;
+
+ @Mock
+ private ContentStore mockContentStore;
+
+ @Mock
+ private NodeService mockNodeService;
+
+ @Mock
+ private ContentData mockContentData;
+
+ @Before
+ public void setup()
+ {
+ openMocks(this);
+ when(mockNodeService.getProperty(NODE_REF, ContentModel.PROP_CONTENT)).thenReturn(mockContentData);
+ when(mockContentData.getContentUrl()).thenReturn("someContentUrl");
+ when(mockNodeService.getProperty(NODE_REF, ContentModel.PROP_NAME)).thenReturn("someFilename");
+ }
+
+ @Test
+ public void testIsContentDirectUrlEnabled_SystemWideIsDisabled()
+ {
+ setupSystemWideDirectAccessConfig(DISABLED);
+ assertFalse("Expected contentDirectUrl to be disabled", contentService.isContentDirectUrlEnabled());
+ verify(mockContentStore, never()).isContentDirectUrlEnabled();
+ }
+
+ @Test
+ public void testIsContentDirectUrlEnabled_SystemWideIsEnabledButStoreIsDisabled()
+ {
+ setupSystemWideDirectAccessConfig(ENABLED);
+ when(mockContentStore.isContentDirectUrlEnabled()).thenReturn(DISABLED);
+ assertFalse("Expected contentDirectUrl to be disabled", contentService.isContentDirectUrlEnabled());
+ }
+
+ @Test
+ public void testIsContentDirectUrlEnabled_SystemWideIsEnabledAndStoreIsEnabled()
+ {
+ setupSystemWideDirectAccessConfig(ENABLED);
+ when(mockContentStore.isContentDirectUrlEnabled()).thenReturn(ENABLED);
+ assertTrue("Expected contentDirectUrl to be enabled", contentService.isContentDirectUrlEnabled());
+ }
+
+ @Test
+ public void testRequestContentDirectUrl_SystemWideIsDisabled()
+ {
+ setupSystemWideDirectAccessConfig(DISABLED);
+ try
+ {
+ contentService.requestContentDirectUrl(NODE_REF, true, 20L);
+ fail("Expected DirectAccessUrlDisabledException");
+ }
+ catch (DirectAccessUrlDisabledException ex)
+ {
+ verify(mockContentStore, never()).isContentDirectUrlEnabled();
+ }
+ }
+
+ @Test
+ public void testRequestContentDirectUrl_SystemWideIsEnabledButStoreIsDisabled()
+ {
+ setupSystemWideDirectAccessConfig(ENABLED);
+ when(mockContentStore.isContentDirectUrlEnabled()).thenReturn(DISABLED);
+
+ DirectAccessUrl directAccessUrl = contentService.requestContentDirectUrl(NODE_REF, true, 20L);
+ assertNull(directAccessUrl);
+ verify(mockContentStore, never()).requestContentDirectUrl(anyString(), eq(true), anyString(), anyLong());
+ }
+
+ @Test
+ public void testRequestContentDirectUrl_StoreIsEnabledButNotImplemented()
+ {
+ setupSystemWideDirectAccessConfig(ENABLED);
+ when(mockContentStore.isContentDirectUrlEnabled()).thenReturn(ENABLED);
+
+ DirectAccessUrl directAccessUrl = contentService.requestContentDirectUrl(NODE_REF, true, 20L);
+ assertNull(directAccessUrl);
+ verify(mockContentStore, times(1)).requestContentDirectUrl(anyString(), eq(true), anyString(), anyLong());
+ }
+
+ /* Helper method to set system-wide direct access url configuration settings */
+ private void setupSystemWideDirectAccessConfig(Boolean isEnabled)
+ {
+ SystemWideDirectUrlConfig sysConfig = new SystemWideDirectUrlConfig();
+ sysConfig.setEnabled(isEnabled);
+ sysConfig.setDefaultExpiryTimeInSec(SYS_DEFAULT_EXPIRY_TIME_IN_SECS);
+ sysConfig.setMaxExpiryTimeInSec(SYS_MAX_EXPIRY_TIME_IN_SECS);
+ sysConfig.validate();
+ contentService.setSystemWideDirectUrlConfig(sysConfig);
+ }
+}
diff --git a/repository/src/test/java/org/alfresco/repo/content/caching/CachingContentStoreTest.java b/repository/src/test/java/org/alfresco/repo/content/caching/CachingContentStoreTest.java
index ffac9eea8b..f35d0b08d4 100644
--- a/repository/src/test/java/org/alfresco/repo/content/caching/CachingContentStoreTest.java
+++ b/repository/src/test/java/org/alfresco/repo/content/caching/CachingContentStoreTest.java
@@ -35,6 +35,7 @@ import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
@@ -493,10 +494,10 @@ public class CachingContentStoreTest
@Test
public void isDirectAccessSupported()
{
- assertFalse(cachingStore.isDirectAccessSupported());
+ assertFalse(cachingStore.isContentDirectUrlEnabled());
- when(backingStore.isDirectAccessSupported()).thenReturn(true);
- assertTrue(cachingStore.isDirectAccessSupported());
+ when(backingStore.isContentDirectUrlEnabled()).thenReturn(true);
+ assertTrue(cachingStore.isContentDirectUrlEnabled());
}
@Test
@@ -504,8 +505,8 @@ public class CachingContentStoreTest
{
try
{
- when(backingStore.getDirectAccessUrl(anyString(), any())).thenThrow(new UnsupportedOperationException());
- cachingStore.getDirectAccessUrl("url", null);
+ when(backingStore.requestContentDirectUrl(anyString(), eq(true), anyString(), anyLong())).thenThrow(new UnsupportedOperationException());
+ cachingStore.requestContentDirectUrl("url", true,"someFile", 30L);
fail();
}
catch (UnsupportedOperationException e)
@@ -517,7 +518,7 @@ public class CachingContentStoreTest
@Test
public void getDirectAccessUrl()
{
- when(backingStore.getDirectAccessUrl(anyString(), any())).thenReturn(new DirectAccessUrl());
- cachingStore.getDirectAccessUrl("url", null);
+ when(backingStore.requestContentDirectUrl(anyString(), eq(true), anyString(), anyLong())).thenReturn(new DirectAccessUrl());
+ cachingStore.requestContentDirectUrl("url", true,"someFile", 30L);
}
}
diff --git a/repository/src/test/java/org/alfresco/repo/content/replication/AggregatingContentStoreTest.java b/repository/src/test/java/org/alfresco/repo/content/replication/AggregatingContentStoreTest.java
index ecfaf17823..585843f155 100644
--- a/repository/src/test/java/org/alfresco/repo/content/replication/AggregatingContentStoreTest.java
+++ b/repository/src/test/java/org/alfresco/repo/content/replication/AggregatingContentStoreTest.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -56,9 +56,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
@@ -191,7 +189,7 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
}
@Test
- public void testIsDirectAccessSupported()
+ public void testIsContentDirectUrlEnabled()
{
// Create the aggregating store
AggregatingContentStore aggStore = new AggregatingContentStore();
@@ -199,21 +197,21 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
aggStore.setSecondaryStores(List.of(secondaryStoreMock));
// By default it is unsupported
- assertFalse(aggStore.isDirectAccessSupported());
+ assertFalse(aggStore.isContentDirectUrlEnabled());
// Supported if at least one store supports direct access
{
- when(primaryStoreMock.isDirectAccessSupported()).thenReturn(false);
- when(secondaryStoreMock.isDirectAccessSupported()).thenReturn(true);
- assertTrue(aggStore.isDirectAccessSupported());
+ when(primaryStoreMock.isContentDirectUrlEnabled()).thenReturn(false);
+ when(secondaryStoreMock.isContentDirectUrlEnabled()).thenReturn(true);
+ assertTrue(aggStore.isContentDirectUrlEnabled());
- when(primaryStoreMock.isDirectAccessSupported()).thenReturn(true);
- when(secondaryStoreMock.isDirectAccessSupported()).thenReturn(true);
- assertTrue(aggStore.isDirectAccessSupported());
+ when(primaryStoreMock.isContentDirectUrlEnabled()).thenReturn(true);
+ when(secondaryStoreMock.isContentDirectUrlEnabled()).thenReturn(true);
+ assertTrue(aggStore.isContentDirectUrlEnabled());
- when(primaryStoreMock.isDirectAccessSupported()).thenReturn(true);
- when(secondaryStoreMock.isDirectAccessSupported()).thenReturn(false);
- assertTrue(aggStore.isDirectAccessSupported());
+ when(primaryStoreMock.isContentDirectUrlEnabled()).thenReturn(true);
+ when(secondaryStoreMock.isContentDirectUrlEnabled()).thenReturn(false);
+ assertTrue(aggStore.isContentDirectUrlEnabled());
}
}
@@ -229,15 +227,15 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
UnsupportedContentUrlException unsupportedContentUrlExc = new UnsupportedContentUrlException(aggStore, "");
// By default it is unsupported
- DirectAccessUrl directAccessUrl = aggStore.getDirectAccessUrl("url", null);
+ DirectAccessUrl directAccessUrl = aggStore.requestContentDirectUrl("url", true, "anyfilename", 30L);
assertNull(directAccessUrl);
// Direct access not supported
try
{
- when(primaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedExc);
- when(secondaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedExc);
- aggStore.getDirectAccessUrl("urlDANotSupported", null);
+ when(primaryStoreMock.requestContentDirectUrl(eq("urlDANotSupported"), any(), any(), any())).thenThrow(unsupportedExc);
+ when(secondaryStoreMock.requestContentDirectUrl(eq("urlDANotSupported"), any(), any(), any())).thenThrow(unsupportedExc);
+ aggStore.requestContentDirectUrl(eq("urlDANotSupported"), true, "anyfilename", 30L);
fail();
}
catch (UnsupportedOperationException e)
@@ -247,9 +245,9 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
try
{
- when(primaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedContentUrlExc);
- when(secondaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedExc);
- aggStore.getDirectAccessUrl("urlDANotSupported", null);
+ when(primaryStoreMock.requestContentDirectUrl(eq("urlDANotSupported"), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
+ when(secondaryStoreMock.requestContentDirectUrl(eq("urlDANotSupported"), any(), any(), any())).thenThrow(unsupportedExc);
+ aggStore.requestContentDirectUrl("urlDANotSupported", true, "anyfilename", 30L);
fail();
}
catch (UnsupportedOperationException e)
@@ -259,9 +257,9 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
try
{
- when(primaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedExc);
- when(secondaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedContentUrlExc);
- aggStore.getDirectAccessUrl("urlDANotSupported", null);
+ when(primaryStoreMock.requestContentDirectUrl(eq("urlDANotSupported"), any(), any(), any())).thenThrow(unsupportedExc);
+ when(secondaryStoreMock.requestContentDirectUrl(eq("urlDANotSupported"), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
+ aggStore.requestContentDirectUrl("urlDANotSupported", true, "anyfilename", 30L);
fail();
}
catch (UnsupportedOperationException e)
@@ -272,9 +270,9 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
// Content url not supported
try
{
- when(primaryStoreMock.getDirectAccessUrl(eq("urlNotSupported"), any())).thenThrow(unsupportedContentUrlExc);
- when(secondaryStoreMock.getDirectAccessUrl(eq("urlNotSupported"), any())).thenThrow(unsupportedContentUrlExc);
- aggStore.getDirectAccessUrl("urlNotSupported", null);
+ when(primaryStoreMock.requestContentDirectUrl(eq("urlNotSupported"), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
+ when(secondaryStoreMock.requestContentDirectUrl(eq("urlNotSupported"), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
+ aggStore.requestContentDirectUrl("urlNotSupported", true, "anyfilename", 30L);
fail();
}
catch (UnsupportedContentUrlException e)
@@ -282,31 +280,31 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
// Expected
}
- when(primaryStoreMock.getDirectAccessUrl(eq("urlPriSupported"), any())).thenReturn(new DirectAccessUrl());
- when(secondaryStoreMock.getDirectAccessUrl(eq("urlPriSupported"), any())).thenThrow(unsupportedExc);
- directAccessUrl = aggStore.getDirectAccessUrl("urlPriSupported", null);
+ when(primaryStoreMock.requestContentDirectUrl(eq("urlPriSupported"), any(), any(), any())).thenReturn(new DirectAccessUrl());
+ when(secondaryStoreMock.requestContentDirectUrl(eq("urlPriSupported"), any(), any(), any())).thenThrow(unsupportedExc);
+ directAccessUrl = aggStore.requestContentDirectUrl("urlPriSupported", true, "anyfilename", 30L);
assertNotNull(directAccessUrl);
- when(primaryStoreMock.getDirectAccessUrl(eq("urlPriSupported"), any())).thenReturn(new DirectAccessUrl());
- when(secondaryStoreMock.getDirectAccessUrl(eq("urlPriSupported"), any())).thenThrow(unsupportedContentUrlExc);
- directAccessUrl = aggStore.getDirectAccessUrl("urlPriSupported", null);
+ when(primaryStoreMock.requestContentDirectUrl(eq("urlPriSupported"), any(), any(), any())).thenReturn(new DirectAccessUrl());
+ when(secondaryStoreMock.requestContentDirectUrl(eq("urlPriSupported"), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
+ directAccessUrl = aggStore.requestContentDirectUrl("urlPriSupported", true, "anyfilename", 30L);
assertNotNull(directAccessUrl);
- when(primaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenThrow(unsupportedExc);
- when(secondaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenReturn(new DirectAccessUrl());
- directAccessUrl = aggStore.getDirectAccessUrl("urlSecSupported", null);
+ when(primaryStoreMock.requestContentDirectUrl(eq("urlSecSupported"), any(), any(), any())).thenThrow(unsupportedExc);
+ when(secondaryStoreMock.requestContentDirectUrl(eq("urlSecSupported"), any(), any(), any())).thenReturn(new DirectAccessUrl());
+ directAccessUrl = aggStore.requestContentDirectUrl("urlSecSupported", true, "anyfilename", 30L);
assertNotNull(directAccessUrl);
- when(primaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenThrow(unsupportedContentUrlExc);
- when(secondaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenReturn(new DirectAccessUrl());
- directAccessUrl = aggStore.getDirectAccessUrl("urlSecSupported", null);
+ when(primaryStoreMock.requestContentDirectUrl(eq("urlSecSupported"), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
+ when(secondaryStoreMock.requestContentDirectUrl(eq("urlSecSupported"), any(), any(), any())).thenReturn(new DirectAccessUrl());
+ directAccessUrl = aggStore.requestContentDirectUrl("urlSecSupported", true, "anyfilename", 30L);
assertNotNull(directAccessUrl);
- when(primaryStoreMock.getDirectAccessUrl(eq("urlPriSupported"), any())).thenReturn(new DirectAccessUrl());
- when(secondaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenReturn(new DirectAccessUrl());
- directAccessUrl = aggStore.getDirectAccessUrl("urlPriSupported", null);
+ when(primaryStoreMock.requestContentDirectUrl(eq("urlPriSupported"), any(), any(), any())).thenReturn(new DirectAccessUrl());
+ when(secondaryStoreMock.requestContentDirectUrl(eq("urlSecSupported"), any(), any(), any())).thenReturn(new DirectAccessUrl());
+ directAccessUrl = aggStore.requestContentDirectUrl("urlPriSupported", true, "anyfilename", 30L);
assertNotNull(directAccessUrl);
- directAccessUrl = aggStore.getDirectAccessUrl("urlSecSupported", null);
+ directAccessUrl = aggStore.requestContentDirectUrl("urlSecSupported", true, "anyfilename", 30L);
assertNotNull(directAccessUrl);
}
}
diff --git a/repository/src/test/java/org/alfresco/repo/version/ContentServiceImplTest.java b/repository/src/test/java/org/alfresco/repo/version/ContentServiceImplTest.java
index 5cebb8acaf..5423fd3077 100644
--- a/repository/src/test/java/org/alfresco/repo/version/ContentServiceImplTest.java
+++ b/repository/src/test/java/org/alfresco/repo/version/ContentServiceImplTest.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -25,18 +25,16 @@
*/
package org.alfresco.repo.version;
-import org.alfresco.error.AlfrescoRuntimeException;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.openMocks;
+
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.ContentStore;
-import org.alfresco.repo.content.EmptyContentReader;
-import org.alfresco.repo.content.MimetypeMap;
-import org.alfresco.repo.content.MimetypeMapTest;
+import org.alfresco.repo.content.directurl.SystemWideDirectUrlConfig;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
-import org.alfresco.service.cmr.repository.NoTransformerException;
import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.namespace.QName;
import org.alfresco.test_category.OwnJVMTestsCategory;
@@ -44,10 +42,11 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.transaction.annotation.Transactional;
-import java.util.Date;
/**
* Tests for getting content readers and writers.
@@ -57,7 +56,9 @@ import java.util.Date;
@Category(OwnJVMTestsCategory.class)
@Transactional
public class ContentServiceImplTest extends BaseVersionStoreTest
-{
+{
+ private static final Boolean ENABLED = Boolean.TRUE;
+
/**
* Test content data
*/
@@ -66,9 +67,14 @@ public class ContentServiceImplTest extends BaseVersionStoreTest
/**
* The version content store
*/
+ @InjectMocks
private ContentService contentService;
+
private ContentStore contentStore;
+ @Mock
+ private SystemWideDirectUrlConfig mockSystemWideDirectUrlConfig;
+
@Before
public void before() throws Exception
{
@@ -139,15 +145,17 @@ public class ContentServiceImplTest extends BaseVersionStoreTest
}
@Test
- public void testWhenGetDirectAccessUrlIsNotSupported()
+ public void testWhenRequestContentDirectUrlIsNotSupported()
{
- assertFalse(contentStore.isDirectAccessSupported());
+ openMocks(this);
+ when(mockSystemWideDirectUrlConfig.isEnabled()).thenReturn(ENABLED);
+ when(mockSystemWideDirectUrlConfig.getDefaultExpiryTimeInSec()).thenReturn(30L);
+ when(mockSystemWideDirectUrlConfig.getMaxExpiryTimeInSec()).thenReturn(300L);
+
+ assertFalse(contentStore.isContentDirectUrlEnabled());
// Set the presigned URL to expire after one minute.
- Date expiresAt = new Date();
- long expTimeMillis = expiresAt.getTime();
- expTimeMillis += 1000 * 60;
- expiresAt.setTime(expTimeMillis);
+ Long validFor = 60L;
try
{
@@ -155,7 +163,7 @@ public class ContentServiceImplTest extends BaseVersionStoreTest
NodeRef nodeRef = this.dbNodeService
.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN, QName.createQName("{test}MyNoContentNode"), TEST_TYPE_QNAME, this.nodeProperties).getChildRef();
- assertEquals(null, contentService.getDirectAccessUrl(nodeRef, expiresAt));
+ assertNull(contentService.requestContentDirectUrl(nodeRef, true, validFor));
fail("nodeRef has no content");
}
catch (IllegalArgumentException e)
@@ -165,7 +173,7 @@ public class ContentServiceImplTest extends BaseVersionStoreTest
try
{
- assertEquals(null, contentService.getDirectAccessUrl(null, null));
+ assertNull(contentService.requestContentDirectUrl(null, true, null));
fail("nodeRef is null");
}
catch (IllegalArgumentException e)
@@ -176,7 +184,7 @@ public class ContentServiceImplTest extends BaseVersionStoreTest
// Create a node with content
NodeRef nodeRef = createNewVersionableNode();
- assertEquals(null, contentService.getDirectAccessUrl(nodeRef, null));
- assertEquals(null, contentService.getDirectAccessUrl(nodeRef, expiresAt));
+ assertNull(contentService.requestContentDirectUrl(nodeRef, true, null));
+ assertNull(contentService.requestContentDirectUrl(nodeRef, true, validFor));
}
}