mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
ACS-406: S3 Connector: support for content direct access urls throws … (#1080)
- added implementation for CachingContentStore and AggregatingContentStore - added tests
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
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;
|
||||
@@ -39,6 +40,7 @@ import org.alfresco.service.cmr.repository.ContentIOException;
|
||||
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.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
@@ -475,4 +477,14 @@ public class CachingContentStore implements ContentStore, ApplicationEventPublis
|
||||
{
|
||||
return this.beanName;
|
||||
}
|
||||
|
||||
public boolean isDirectAccessSupported()
|
||||
{
|
||||
return backingStore.isDirectAccessSupported();
|
||||
}
|
||||
|
||||
public DirectAccessUrl getDirectAccessUrl(String contentUrl, Date expiresAt)
|
||||
{
|
||||
return backingStore.getDirectAccessUrl(contentUrl, expiresAt);
|
||||
}
|
||||
}
|
||||
|
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
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;
|
||||
@@ -39,6 +40,7 @@ import org.alfresco.repo.content.caching.CachingContentStore;
|
||||
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.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
@@ -262,4 +264,115 @@ public class AggregatingContentStore extends AbstractContentStore
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns <tt>true</tt> if at least one store supports direct access
|
||||
*/
|
||||
public boolean isDirectAccessSupported()
|
||||
{
|
||||
// Check the primary store
|
||||
boolean isDirectAccessSupported = primaryStore.isDirectAccessSupported();
|
||||
|
||||
if (!isDirectAccessSupported)
|
||||
{
|
||||
// Direct access is not supported by the primary store so we have to check the
|
||||
// other stores
|
||||
for (ContentStore store : secondaryStores)
|
||||
{
|
||||
|
||||
isDirectAccessSupported = store.isDirectAccessSupported();
|
||||
|
||||
if (isDirectAccessSupported)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return isDirectAccessSupported;
|
||||
}
|
||||
|
||||
public DirectAccessUrl getDirectAccessUrl(String contentUrl, Date expiresAt)
|
||||
{
|
||||
if (primaryStore == null)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("ReplicatingContentStore not initialised");
|
||||
}
|
||||
|
||||
// get a read lock so that we are sure that no replication is underway
|
||||
readLock.lock();
|
||||
try
|
||||
{
|
||||
// Keep track of the unsupported state of the content URL - it might be a rubbish URL
|
||||
boolean contentUrlSupported = true;
|
||||
boolean directAccessUrlSupported = true;
|
||||
|
||||
DirectAccessUrl directAccessUrl = null;
|
||||
|
||||
// Check the primary store
|
||||
try
|
||||
{
|
||||
directAccessUrl = primaryStore.getDirectAccessUrl(contentUrl, expiresAt);
|
||||
}
|
||||
catch (UnsupportedOperationException e)
|
||||
{
|
||||
// The store does not support direct access URL
|
||||
directAccessUrlSupported = false;
|
||||
}
|
||||
catch (UnsupportedContentUrlException e)
|
||||
{
|
||||
// The store can't handle the content URL
|
||||
contentUrlSupported = false;
|
||||
}
|
||||
|
||||
if (directAccessUrl != null)
|
||||
{
|
||||
return directAccessUrl;
|
||||
}
|
||||
|
||||
// the content is not in the primary store so we have to go looking for it
|
||||
for (ContentStore store : secondaryStores)
|
||||
{
|
||||
try
|
||||
{
|
||||
directAccessUrl = store.getDirectAccessUrl(contentUrl, expiresAt);
|
||||
}
|
||||
catch (UnsupportedOperationException e)
|
||||
{
|
||||
// The store does not support direct access URL
|
||||
directAccessUrlSupported = false;
|
||||
}
|
||||
catch (UnsupportedContentUrlException e)
|
||||
{
|
||||
// The store can't handle the content URL
|
||||
contentUrlSupported = false;
|
||||
}
|
||||
|
||||
if (directAccessUrl != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (directAccessUrl == null)
|
||||
{
|
||||
if (!directAccessUrlSupported)
|
||||
{
|
||||
// The direct access URL was not supported
|
||||
throw new UnsupportedOperationException("Retrieving direct access URLs is not supported by this content store.");
|
||||
}
|
||||
else if (!contentUrlSupported)
|
||||
{
|
||||
// The content URL was not supported
|
||||
throw new UnsupportedContentUrlException(this, contentUrl);
|
||||
}
|
||||
}
|
||||
|
||||
return directAccessUrl;
|
||||
}
|
||||
finally
|
||||
{
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -31,6 +31,7 @@ import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
@@ -54,6 +55,7 @@ import org.alfresco.service.cmr.repository.ContentIOException;
|
||||
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.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -487,4 +489,35 @@ public class CachingContentStoreTest
|
||||
when(backingStore.delete("url")).thenReturn(false);
|
||||
assertFalse(cachingStore.delete("url"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isDirectAccessSupported()
|
||||
{
|
||||
assertFalse(cachingStore.isDirectAccessSupported());
|
||||
|
||||
when(backingStore.isDirectAccessSupported()).thenReturn(true);
|
||||
assertTrue(cachingStore.isDirectAccessSupported());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDirectAccessUrlUnsupported()
|
||||
{
|
||||
try
|
||||
{
|
||||
when(backingStore.getDirectAccessUrl(anyString(), any())).thenThrow(new UnsupportedOperationException());
|
||||
cachingStore.getDirectAccessUrl("url", null);
|
||||
fail();
|
||||
}
|
||||
catch (UnsupportedOperationException e)
|
||||
{
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDirectAccessUrl()
|
||||
{
|
||||
when(backingStore.getDirectAccessUrl(anyString(), any())).thenReturn(new DirectAccessUrl());
|
||||
cachingStore.getDirectAccessUrl("url", null);
|
||||
}
|
||||
}
|
||||
|
@@ -32,17 +32,33 @@ import java.util.List;
|
||||
import org.alfresco.repo.content.AbstractWritableContentStoreTest;
|
||||
import org.alfresco.repo.content.ContentContext;
|
||||
import org.alfresco.repo.content.ContentStore;
|
||||
import org.alfresco.repo.content.UnsupportedContentUrlException;
|
||||
import org.alfresco.repo.content.filestore.FileContentStore;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.DirectAccessUrl;
|
||||
import org.alfresco.test_category.OwnJVMTestsCategory;
|
||||
import org.alfresco.util.GUID;
|
||||
import org.alfresco.util.TempFileProvider;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.categories.Category;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Tests read and write functionality for the aggregating store.
|
||||
@@ -62,6 +78,16 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
|
||||
private ContentStore primaryStore;
|
||||
private List<ContentStore> secondaryStores;
|
||||
|
||||
@Mock
|
||||
ContentStore primaryStoreMock;
|
||||
@Mock
|
||||
ContentStore secondaryStoreMock;
|
||||
@Mock
|
||||
AggregatingContentStore aggregatingContentStoreMock;
|
||||
|
||||
@Rule
|
||||
public MockitoRule rule = MockitoJUnit.rule();
|
||||
|
||||
@Before
|
||||
public void before() throws Exception
|
||||
{
|
||||
@@ -163,5 +189,123 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
|
||||
checkForUrl(contentUrl, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsDirectAccessSupported()
|
||||
{
|
||||
// Create the aggregating store
|
||||
AggregatingContentStore aggStore = new AggregatingContentStore();
|
||||
aggStore.setPrimaryStore(primaryStoreMock);
|
||||
aggStore.setSecondaryStores(List.of(secondaryStoreMock));
|
||||
|
||||
// By default it is unsupported
|
||||
assertFalse(aggStore.isDirectAccessSupported());
|
||||
|
||||
// Supported if at least one store supports direct access
|
||||
{
|
||||
when(primaryStoreMock.isDirectAccessSupported()).thenReturn(false);
|
||||
when(secondaryStoreMock.isDirectAccessSupported()).thenReturn(true);
|
||||
assertTrue(aggStore.isDirectAccessSupported());
|
||||
|
||||
when(primaryStoreMock.isDirectAccessSupported()).thenReturn(true);
|
||||
when(secondaryStoreMock.isDirectAccessSupported()).thenReturn(true);
|
||||
assertTrue(aggStore.isDirectAccessSupported());
|
||||
|
||||
when(primaryStoreMock.isDirectAccessSupported()).thenReturn(true);
|
||||
when(secondaryStoreMock.isDirectAccessSupported()).thenReturn(false);
|
||||
assertTrue(aggStore.isDirectAccessSupported());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDirectAccessUrl()
|
||||
{
|
||||
// Create the aggregating store
|
||||
AggregatingContentStore aggStore = new AggregatingContentStore();
|
||||
aggStore.setPrimaryStore(primaryStoreMock);
|
||||
aggStore.setSecondaryStores(List.of(secondaryStoreMock));
|
||||
|
||||
UnsupportedOperationException unsupportedExc = new UnsupportedOperationException();
|
||||
UnsupportedContentUrlException unsupportedContentUrlExc = new UnsupportedContentUrlException(aggStore, "");
|
||||
|
||||
// By default it is unsupported
|
||||
DirectAccessUrl directAccessUrl = aggStore.getDirectAccessUrl("url", null);
|
||||
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);
|
||||
fail();
|
||||
}
|
||||
catch (UnsupportedOperationException e)
|
||||
{
|
||||
// Expected
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
when(primaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedContentUrlExc);
|
||||
when(secondaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedExc);
|
||||
aggStore.getDirectAccessUrl("urlDANotSupported", null);
|
||||
fail();
|
||||
}
|
||||
catch (UnsupportedOperationException e)
|
||||
{
|
||||
// Expected
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
when(primaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedExc);
|
||||
when(secondaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedContentUrlExc);
|
||||
aggStore.getDirectAccessUrl("urlDANotSupported", null);
|
||||
fail();
|
||||
}
|
||||
catch (UnsupportedOperationException e)
|
||||
{
|
||||
// Expected
|
||||
}
|
||||
|
||||
// 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);
|
||||
fail();
|
||||
}
|
||||
catch (UnsupportedContentUrlException e)
|
||||
{
|
||||
// Expected
|
||||
}
|
||||
|
||||
when(primaryStoreMock.getDirectAccessUrl(eq("urlPriSupported"), any())).thenReturn(new DirectAccessUrl());
|
||||
when(secondaryStoreMock.getDirectAccessUrl(eq("urlPriSupported"), any())).thenThrow(unsupportedExc);
|
||||
directAccessUrl = aggStore.getDirectAccessUrl("urlPriSupported", null);
|
||||
assertNotNull(directAccessUrl);
|
||||
|
||||
when(primaryStoreMock.getDirectAccessUrl(eq("urlPriSupported"), any())).thenReturn(new DirectAccessUrl());
|
||||
when(secondaryStoreMock.getDirectAccessUrl(eq("urlPriSupported"), any())).thenThrow(unsupportedContentUrlExc);
|
||||
directAccessUrl = aggStore.getDirectAccessUrl("urlPriSupported", null);
|
||||
assertNotNull(directAccessUrl);
|
||||
|
||||
when(primaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenThrow(unsupportedExc);
|
||||
when(secondaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenReturn(new DirectAccessUrl());
|
||||
directAccessUrl = aggStore.getDirectAccessUrl("urlSecSupported", null);
|
||||
assertNotNull(directAccessUrl);
|
||||
|
||||
when(primaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenThrow(unsupportedContentUrlExc);
|
||||
when(secondaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenReturn(new DirectAccessUrl());
|
||||
directAccessUrl = aggStore.getDirectAccessUrl("urlSecSupported", null);
|
||||
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);
|
||||
assertNotNull(directAccessUrl);
|
||||
directAccessUrl = aggStore.getDirectAccessUrl("urlSecSupported", null);
|
||||
assertNotNull(directAccessUrl);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user