package org.alfresco.repo.content;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.util.HashSet;
import java.util.Set;
import javax.transaction.UserTransaction;
import org.alfresco.repo.content.ContentStore.ContentUrlHandler;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ApplicationContextHelper;
import org.alfresco.util.BaseApplicationContextHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
import org.springframework.context.ApplicationContext;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* Abstract base class that provides a set of tests for implementations
* of {@link ContentStore}.
*
* @see ContentStore
* @see org.alfresco.service.cmr.repository.ContentReader
* @see org.alfresco.service.cmr.repository.ContentWriter
*
* @author sglover
* @author Derek Hulley
*/
public abstract class AbstractReadOnlyContentStoreTest
{
protected static ApplicationContext ctx;
private static Log logger = LogFactory.getLog(AbstractReadOnlyContentStoreTest.class);
@Rule public TestName name = new TestName();
protected String getName()
{
return name.getMethodName();
}
protected TransactionService transactionService;
private UserTransaction txn;
public AbstractReadOnlyContentStoreTest()
{
super();
}
@BeforeClass
public static void beforeClass() throws Exception
{
ctx = BaseApplicationContextHelper.getApplicationContext(ApplicationContextHelper.CONFIG_LOCATIONS);
}
/**
* Starts a transaction
*/
@Before
public void before() throws Exception
{
transactionService = (TransactionService) ctx.getBean("TransactionService");
txn = transactionService.getUserTransaction();
txn.begin();
}
/**
* Rolls back the transaction
*/
@After
public void after() throws Exception
{
try { txn.rollback(); } catch (Throwable e) {e.printStackTrace();}
}
/**
* Fetch the store to be used during a test. This method is invoked once per test - it is
* therefore safe to use setUp
to initialise resources.
*
* Usually tests will construct a static instance of the store to use throughout all the
* tests.
*
* @return Returns the same instance of a store for all invocations.
*/
protected abstract ContentStore getStore();
/**
* Gets a reader for the given content URL from the store
*
* @see #getStore()
*/
protected final ContentReader getReader(String contentUrl)
{
return getStore().getReader(contentUrl);
}
/**
* Fetch a valid URL from the store. The default implementation will attempt to get
* all the available URLs from the store and pick the first one. Writable store tests
* can create some content to be sure of its existence.
*
* @return
* Return any valid URL for the store, or null if the store is empty.
*/
@SuppressWarnings("deprecation")
protected String getExistingContentUrl()
{
ContentStore store = getStore();
try
{
final Set
* Only executes if the reader implements {@link RandomAccessContent}.
*/
@Test
public void testRandomAccessRead() throws Exception
{
ContentStore store = getStore();
String contentUrl = getExistingContentUrl();
if (contentUrl == null)
{
logger.warn("Store test testRandomAccessRead not possible on " + store.getClass().getName());
return;
}
// Get the reader
ContentReader reader = store.getReader(contentUrl);
assertNotNull("Reader should never be null", reader);
FileChannel fileChannel = reader.getFileChannel();
assertNotNull("No channel given", fileChannel);
// check that no other content access is allowed
try
{
reader.getReadableChannel();
fail("Second channel access allowed");
}
catch (RuntimeException e)
{
// expected
}
fileChannel.close();
}
@Test
public void testBlockedWriteOperations() throws Exception
{
ContentStore store = getStore();
if (store.isWriteSupported())
{
// Just ignore this test
return;
}
// Ensure that we can't get a writer
try
{
store.getWriter(ContentStore.NEW_CONTENT_CONTEXT);
fail("Read-only store provided a writer: " + store);
}
catch (UnsupportedOperationException e)
{
// Expected
}
String contentUrl = getExistingContentUrl();
if (contentUrl == null)
{
logger.warn("Store test testBlockedWriteOperations not possible on " + store.getClass().getName());
return;
}
// Ensure that we can't delete a URL
try
{
store.delete(contentUrl);
fail("Read-only store allowed deletion: " + store);
}
catch (UnsupportedOperationException e)
{
// Expected
}
}
}