mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-06-16 17:55:15 +00:00
8372: Merged V2.1 to V2.2 8314: Merged V2.0 to V2.1 7750: Fix for ACT-475: ContentStoreCleaner causes OutOfMemoryError 8332: Made content URL column larger to accommodate the extra locale info present in 2.1 8334: Build fix: V2.1 tighter on authentication for getTempWriter 8376: Merged V2.1 to V2.2 8325: Fix for AWC-1089 8361: Workaround for WCM-882: All metadata extracters can now handle zero length files git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@8497 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
258 lines
8.8 KiB
Java
258 lines
8.8 KiB
Java
/*
|
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
|
|
* This program 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 General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
* As a special exception to the terms and conditions of version 2.0 of
|
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
|
* FLOSS exception. You should have recieved a copy of the text describing
|
|
* the FLOSS exception, and it is also available here:
|
|
* http://www.alfresco.com/legal/licensing"
|
|
*/
|
|
package org.alfresco.repo.content;
|
|
|
|
import java.io.File;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.Date;
|
|
import java.util.List;
|
|
|
|
import net.sf.ehcache.Cache;
|
|
import net.sf.ehcache.CacheManager;
|
|
|
|
import org.alfresco.repo.cache.EhCacheAdapter;
|
|
import org.alfresco.repo.content.filestore.FileContentStore;
|
|
import org.alfresco.service.cmr.repository.ContentIOException;
|
|
import org.alfresco.service.cmr.repository.ContentReader;
|
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
|
import org.alfresco.util.TempFileProvider;
|
|
|
|
/**
|
|
* Ensures that the routing of URLs based on context is working. A combination
|
|
* of fully featured and incompletely featured stores is used to ensure that
|
|
* all routing scenarios are handled.
|
|
*
|
|
* @see AbstractRoutingContentStore
|
|
* @since 2.1
|
|
*
|
|
* @author Derek Hulley
|
|
*/
|
|
public class RoutingContentStoreTest extends AbstractWritableContentStoreTest
|
|
{
|
|
private ContentStore storeA;
|
|
private ContentStore storeB;
|
|
private ContentStore storeC;
|
|
private ContentStore storeD;
|
|
private ContentStore routingStore;
|
|
|
|
@Override
|
|
public void setUp() throws Exception
|
|
{
|
|
super.setUp();
|
|
File tempDir = TempFileProvider.getTempDir();
|
|
// Create a subdirectory for A
|
|
File storeADir = new File(tempDir, "A");
|
|
storeA = new FileContentStore(storeADir);
|
|
// Create a subdirectory for B
|
|
File storeBDir = new File(tempDir, "B");
|
|
storeB = new FileContentStore(storeBDir);
|
|
// Create a subdirectory for C
|
|
File storeCDir = new File(tempDir, "C");
|
|
storeC = new DumbReadOnlyFileStore(new FileContentStore(storeCDir));
|
|
// No subdirectory for D
|
|
storeD = new SupportsNoUrlFormatStore();
|
|
// Create the routing store
|
|
routingStore = new RandomRoutingContentStore(storeA, storeB, storeC, storeD);
|
|
}
|
|
|
|
@Override
|
|
protected ContentStore getStore()
|
|
{
|
|
return routingStore;
|
|
}
|
|
|
|
public void testSetUp() throws Exception
|
|
{
|
|
assertNotNull(routingStore);
|
|
}
|
|
|
|
private void checkForContent(String contentUrl, String content)
|
|
{
|
|
for (ContentStore store : new ContentStore[] {storeA, storeB})
|
|
{
|
|
// Does the store have it
|
|
if (store.exists(contentUrl))
|
|
{
|
|
// Check it
|
|
ContentReader reader = store.getReader(contentUrl);
|
|
String checkContent = reader.getContentString();
|
|
assertEquals("Content found but is incorrect", content, checkContent);
|
|
return;
|
|
}
|
|
}
|
|
fail("Content not found in any of the stores: " + contentUrl);
|
|
}
|
|
|
|
/**
|
|
* Checks that requests for missing content URLs are served.
|
|
*/
|
|
public void testMissingUrl()
|
|
{
|
|
String missingContentUrl = FileContentStore.createNewFileStoreUrl();
|
|
|
|
ContentReader reader = routingStore.getReader(missingContentUrl);
|
|
assertNotNull("Missing URL should not return null", reader);
|
|
assertFalse("Empty reader should say content doesn't exist.", reader.exists());
|
|
try
|
|
{
|
|
reader.getContentString();
|
|
fail("Empty reader cannot return content.");
|
|
}
|
|
catch (Throwable e)
|
|
{
|
|
// Expected
|
|
}
|
|
}
|
|
|
|
public void testGeneralUse()
|
|
{
|
|
for (int i = 0 ; i < 20; i++)
|
|
{
|
|
ContentContext contentContext = new ContentContext(null, null);
|
|
ContentWriter writer = routingStore.getWriter(contentContext);
|
|
String content = "This was generated by " + this.getClass().getName() + "#" + getName() + " number " + i;
|
|
writer.putContent(content);
|
|
// Check that it exists
|
|
String contentUrl = writer.getContentUrl();
|
|
checkForContent(contentUrl, content);
|
|
|
|
// Now go direct to the routing store and check that it is able to find the appropriate URLs
|
|
ContentReader reader = routingStore.getReader(contentUrl);
|
|
assertNotNull("Null reader returned", reader);
|
|
assertTrue("Reader should be onto live content", reader.exists());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A test routing store that directs content writes to a randomly-chosen store.
|
|
* Matching of content URLs back to the stores is handled by the base class.
|
|
*
|
|
* @author Derek Hulley
|
|
*/
|
|
private static class RandomRoutingContentStore extends AbstractRoutingContentStore
|
|
{
|
|
private List<ContentStore> stores;
|
|
|
|
public RandomRoutingContentStore(ContentStore ... stores)
|
|
{
|
|
this.stores = new ArrayList<ContentStore>(5);
|
|
for (ContentStore store : stores)
|
|
{
|
|
this.stores.add(store);
|
|
}
|
|
Cache ehCache = new Cache("RandomRoutingContentStore", 50, false, true, 0L, 0L);
|
|
CacheManager cacheManager = new CacheManager();
|
|
cacheManager.addCache(ehCache);
|
|
EhCacheAdapter<String, ContentStore> cache = new EhCacheAdapter<String, ContentStore>();
|
|
cache.setCache(ehCache);
|
|
super.setStoresCache(cache);
|
|
}
|
|
|
|
@Override
|
|
protected List<ContentStore> getAllStores()
|
|
{
|
|
return stores;
|
|
}
|
|
|
|
@Override
|
|
protected ContentStore selectWriteStore(ContentContext ctx)
|
|
{
|
|
// Shuffle the list of writable stores
|
|
List<ContentStore> shuffled = new ArrayList<ContentStore>(stores);
|
|
Collections.shuffle(shuffled);
|
|
// Pick the first writable store
|
|
for (ContentStore store : shuffled)
|
|
{
|
|
if (store.isWriteSupported())
|
|
{
|
|
return store;
|
|
}
|
|
}
|
|
// Nothing found
|
|
fail("A request came for a writer when there is no writable store to choose from");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The simplest possible store.
|
|
*
|
|
* @author Derek Hulley
|
|
*/
|
|
private static class DumbReadOnlyFileStore extends AbstractContentStore
|
|
{
|
|
FileContentStore fileStore;
|
|
public DumbReadOnlyFileStore(FileContentStore fileStore)
|
|
{
|
|
this.fileStore = fileStore;
|
|
}
|
|
|
|
public boolean isWriteSupported()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public ContentReader getReader(String contentUrl)
|
|
{
|
|
return fileStore.getReader(contentUrl);
|
|
}
|
|
|
|
@Override
|
|
public void getUrls(Date createdAfter, Date createdBefore, ContentUrlHandler handler) throws ContentIOException
|
|
{
|
|
fileStore.getUrls(createdAfter, createdBefore, handler);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This store supports nothing. It is designed to catch the routing code out.
|
|
*
|
|
* @author Derek Hulley
|
|
*/
|
|
private static class SupportsNoUrlFormatStore extends AbstractContentStore
|
|
{
|
|
public SupportsNoUrlFormatStore()
|
|
{
|
|
}
|
|
|
|
public boolean isWriteSupported()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public ContentReader getReader(String contentUrl)
|
|
{
|
|
throw new UnsupportedContentUrlException(this, contentUrl);
|
|
}
|
|
|
|
@Override
|
|
public void getUrls(Date createdAfter, Date createdBefore, ContentUrlHandler handler) throws ContentIOException
|
|
{
|
|
throw new UnsupportedOperationException("getUrls not supported");
|
|
}
|
|
}
|
|
}
|