diff --git a/source/java/org/alfresco/repo/content/caching/CachingContentStore.java b/source/java/org/alfresco/repo/content/caching/CachingContentStore.java index 93d77b09d0..a92dbaff34 100644 --- a/source/java/org/alfresco/repo/content/caching/CachingContentStore.java +++ b/source/java/org/alfresco/repo/content/caching/CachingContentStore.java @@ -27,6 +27,8 @@ import org.alfresco.repo.content.ContentContext; import org.alfresco.repo.content.ContentStore; import org.alfresco.repo.content.caching.quota.QuotaManagerStrategy; import org.alfresco.repo.content.caching.quota.UnlimitedQuotaStrategy; +import org.alfresco.repo.content.filestore.FileContentStore; +import org.alfresco.repo.content.filestore.SpoofedTextContentReader; import org.alfresco.service.cmr.repository.ContentIOException; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentStreamListener; @@ -46,6 +48,9 @@ import org.springframework.context.ApplicationEventPublisherAware; * slower that FileContentStore - otherwise performance may actually degrade from its use. *
* It is important that cacheOnInbound is set to true for exceptionally slow backing stores. + *
+ * This store handles the {@link FileContentStore#SPOOF_PROTOCOL} and can be used to wrap stores + * that do not handle the protocol out of the box e.g. the S3 connector's store. * * @author Matt Ward */ @@ -121,15 +126,39 @@ public class CachingContentStore implements ContentStore, ApplicationEventPublis return backingStore.getRootLocation(); } + /** + * {@inheritDoc} + *
+ * For {@link #SPOOF_PROTOCOL spoofed} URLs, the URL always exists. + */ @Override public boolean exists(String contentUrl) { - return backingStore.exists(contentUrl); + if (contentUrl.startsWith(FileContentStore.SPOOF_PROTOCOL)) + { + return true; + } + else + { + return backingStore.exists(contentUrl); + } } + /** + * {@inheritDoc} + *
+ * This store handles the {@link FileContentStore#SPOOF_PROTOCOL} so that underlying stores do not need + * to implement anything related to spoofing. + */ @Override public ContentReader getReader(String contentUrl) { + // Handle the spoofed URL + if (contentUrl.startsWith(FileContentStore.SPOOF_PROTOCOL)) + { + return new SpoofedTextContentReader(contentUrl); + } + // Use pool of locks - which one is determined by a hash of the URL. // This will stop the content from being read/cached multiple times from the backing store // when it should only be read once - cached versions should be returned after that. @@ -317,6 +346,12 @@ public class CachingContentStore implements ContentStore, ApplicationEventPublis @Override public boolean delete(String contentUrl) { + if (contentUrl.startsWith(FileContentStore.SPOOF_PROTOCOL)) + { + // This is not a failure but the content can never actually be deleted + return false; + } + ReentrantReadWriteLock readWriteLock = readWriteLock(contentUrl); ReadLock readLock = readWriteLock.readLock(); readLock.lock(); diff --git a/source/java/org/alfresco/repo/content/filestore/FileContentStore.java b/source/java/org/alfresco/repo/content/filestore/FileContentStore.java index e8f6864787..a4521947c6 100644 --- a/source/java/org/alfresco/repo/content/filestore/FileContentStore.java +++ b/source/java/org/alfresco/repo/content/filestore/FileContentStore.java @@ -429,7 +429,7 @@ public class FileContentStore /** * This implementation requires that the URL start with - * {@link FileContentStore#STORE_PROTOCOL }. + * {@link FileContentStore#STORE_PROTOCOL } or {@link FileContentStore#SPOOF_PROTOCOL } */ public ContentReader getReader(String contentUrl) { diff --git a/source/test-java/org/alfresco/repo/content/caching/CachingContentStoreTest.java b/source/test-java/org/alfresco/repo/content/caching/CachingContentStoreTest.java index 7c76763429..4daf0833fe 100644 --- a/source/test-java/org/alfresco/repo/content/caching/CachingContentStoreTest.java +++ b/source/test-java/org/alfresco/repo/content/caching/CachingContentStoreTest.java @@ -23,6 +23,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; + import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.anyString; @@ -40,6 +41,7 @@ import org.alfresco.repo.content.ContentContext; import org.alfresco.repo.content.ContentStore; import org.alfresco.repo.content.caching.quota.QuotaManagerStrategy; import org.alfresco.repo.content.caching.quota.UnlimitedQuotaStrategy; +import org.alfresco.repo.content.filestore.SpoofedTextContentReader; import org.alfresco.service.cmr.repository.ContentIOException; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentStreamListener; @@ -371,6 +373,41 @@ public class CachingContentStoreTest verify(bsWriter).setMimetype("not/real/mimetype"); } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Tests for spoofed content follow... + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + @Test + public void spoofedGetReader() + { + cachingStore = new CachingContentStore(backingStore, cache, true); + String url = SpoofedTextContentReader.createContentUrl(Locale.ENGLISH, 0L, 1024L); + ContentReader reader = cachingStore.getReader(url); + assertTrue(reader.exists()); + assertEquals(1024, reader.getSize()); + verify(backingStore, never()).getReader(anyString()); + } + + @Test + public void spoofedDelete() + { + cachingStore = new CachingContentStore(backingStore, cache, true); + String url = SpoofedTextContentReader.createContentUrl(Locale.ENGLISH, 0L, 1024L); + boolean deleted = cachingStore.delete(url); + assertFalse(deleted); + verify(backingStore, never()).delete(anyString()); + } + + @Test + public void spoofedExists() + { + cachingStore = new CachingContentStore(backingStore, cache, true); + String url = SpoofedTextContentReader.createContentUrl(Locale.ENGLISH, 0L, 1024L); + boolean exists = cachingStore.exists(url); + assertTrue(exists); + verify(backingStore, never()).exists(anyString()); + } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Tests for delegated methods follow... ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////